@takaro/modules 0.0.0-next.09a7ca1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (352) hide show
  1. package/README.md +3 -0
  2. package/dist/BuiltinModule.d.ts +62 -0
  3. package/dist/BuiltinModule.d.ts.map +1 -0
  4. package/dist/BuiltinModule.js +245 -0
  5. package/dist/BuiltinModule.js.map +1 -0
  6. package/dist/community-modules.json +21 -0
  7. package/dist/dto/base.d.ts +7 -0
  8. package/dist/dto/base.d.ts.map +1 -0
  9. package/dist/dto/base.js +28 -0
  10. package/dist/dto/base.js.map +1 -0
  11. package/dist/dto/discordEvents.d.ts +32 -0
  12. package/dist/dto/discordEvents.d.ts.map +1 -0
  13. package/dist/dto/discordEvents.js +92 -0
  14. package/dist/dto/discordEvents.js.map +1 -0
  15. package/dist/dto/gameEvents.d.ts +83 -0
  16. package/dist/dto/gameEvents.d.ts.map +1 -0
  17. package/dist/dto/gameEvents.js +205 -0
  18. package/dist/dto/gameEvents.js.map +1 -0
  19. package/dist/dto/index.d.ts +54 -0
  20. package/dist/dto/index.d.ts.map +1 -0
  21. package/dist/dto/index.js +18 -0
  22. package/dist/dto/index.js.map +1 -0
  23. package/dist/dto/takaroEvents.d.ts +276 -0
  24. package/dist/dto/takaroEvents.d.ts.map +1 -0
  25. package/dist/dto/takaroEvents.js +794 -0
  26. package/dist/dto/takaroEvents.js.map +1 -0
  27. package/dist/main.d.ts +5 -0
  28. package/dist/main.d.ts.map +1 -0
  29. package/dist/main.js +35 -0
  30. package/dist/main.js.map +1 -0
  31. package/dist/modules/chatBridge/hooks/DiscordToGame.d.ts +2 -0
  32. package/dist/modules/chatBridge/hooks/DiscordToGame.d.ts.map +1 -0
  33. package/dist/modules/chatBridge/hooks/DiscordToGame.js +18 -0
  34. package/dist/modules/chatBridge/hooks/DiscordToGame.js.map +1 -0
  35. package/dist/modules/chatBridge/hooks/GameToDiscord.d.ts +2 -0
  36. package/dist/modules/chatBridge/hooks/GameToDiscord.d.ts.map +1 -0
  37. package/dist/modules/chatBridge/hooks/GameToDiscord.js +14 -0
  38. package/dist/modules/chatBridge/hooks/GameToDiscord.js.map +1 -0
  39. package/dist/modules/chatBridge/hooks/PlayerConnected.d.ts +2 -0
  40. package/dist/modules/chatBridge/hooks/PlayerConnected.d.ts.map +1 -0
  41. package/dist/modules/chatBridge/hooks/PlayerConnected.js +9 -0
  42. package/dist/modules/chatBridge/hooks/PlayerConnected.js.map +1 -0
  43. package/dist/modules/chatBridge/hooks/PlayerDisconnected.d.ts +2 -0
  44. package/dist/modules/chatBridge/hooks/PlayerDisconnected.d.ts.map +1 -0
  45. package/dist/modules/chatBridge/hooks/PlayerDisconnected.js +9 -0
  46. package/dist/modules/chatBridge/hooks/PlayerDisconnected.js.map +1 -0
  47. package/dist/modules/chatBridge/index.d.ts +5 -0
  48. package/dist/modules/chatBridge/index.d.ts.map +1 -0
  49. package/dist/modules/chatBridge/index.js +64 -0
  50. package/dist/modules/chatBridge/index.js.map +1 -0
  51. package/dist/modules/dailyRewards/commands/daily.d.ts +2 -0
  52. package/dist/modules/dailyRewards/commands/daily.d.ts.map +1 -0
  53. package/dist/modules/dailyRewards/commands/daily.js +103 -0
  54. package/dist/modules/dailyRewards/commands/daily.js.map +1 -0
  55. package/dist/modules/dailyRewards/commands/streak.d.ts +2 -0
  56. package/dist/modules/dailyRewards/commands/streak.d.ts.map +1 -0
  57. package/dist/modules/dailyRewards/commands/streak.js +34 -0
  58. package/dist/modules/dailyRewards/commands/streak.js.map +1 -0
  59. package/dist/modules/dailyRewards/commands/topstreak.d.ts +2 -0
  60. package/dist/modules/dailyRewards/commands/topstreak.d.ts.map +1 -0
  61. package/dist/modules/dailyRewards/commands/topstreak.js +44 -0
  62. package/dist/modules/dailyRewards/commands/topstreak.js.map +1 -0
  63. package/dist/modules/dailyRewards/functions/utils.d.ts +6 -0
  64. package/dist/modules/dailyRewards/functions/utils.d.ts.map +1 -0
  65. package/dist/modules/dailyRewards/functions/utils.js +32 -0
  66. package/dist/modules/dailyRewards/functions/utils.js.map +1 -0
  67. package/dist/modules/dailyRewards/hooks/dailyLoginCheck.d.ts +2 -0
  68. package/dist/modules/dailyRewards/hooks/dailyLoginCheck.d.ts.map +1 -0
  69. package/dist/modules/dailyRewards/hooks/dailyLoginCheck.js +19 -0
  70. package/dist/modules/dailyRewards/hooks/dailyLoginCheck.js.map +1 -0
  71. package/dist/modules/dailyRewards/index.d.ts +5 -0
  72. package/dist/modules/dailyRewards/index.d.ts.map +1 -0
  73. package/dist/modules/dailyRewards/index.js +127 -0
  74. package/dist/modules/dailyRewards/index.js.map +1 -0
  75. package/dist/modules/economyUtils/commands/balance.d.ts +2 -0
  76. package/dist/modules/economyUtils/commands/balance.d.ts.map +1 -0
  77. package/dist/modules/economyUtils/commands/balance.js +7 -0
  78. package/dist/modules/economyUtils/commands/balance.js.map +1 -0
  79. package/dist/modules/economyUtils/commands/claim.d.ts +2 -0
  80. package/dist/modules/economyUtils/commands/claim.d.ts.map +1 -0
  81. package/dist/modules/economyUtils/commands/claim.js +35 -0
  82. package/dist/modules/economyUtils/commands/claim.js.map +1 -0
  83. package/dist/modules/economyUtils/commands/confirmTransfer.d.ts +2 -0
  84. package/dist/modules/economyUtils/commands/confirmTransfer.d.ts.map +1 -0
  85. package/dist/modules/economyUtils/commands/confirmTransfer.js +38 -0
  86. package/dist/modules/economyUtils/commands/confirmTransfer.js.map +1 -0
  87. package/dist/modules/economyUtils/commands/grantCurrency.d.ts +2 -0
  88. package/dist/modules/economyUtils/commands/grantCurrency.d.ts.map +1 -0
  89. package/dist/modules/economyUtils/commands/grantCurrency.js +28 -0
  90. package/dist/modules/economyUtils/commands/grantCurrency.js.map +1 -0
  91. package/dist/modules/economyUtils/commands/revokeCurrency.d.ts +2 -0
  92. package/dist/modules/economyUtils/commands/revokeCurrency.d.ts.map +1 -0
  93. package/dist/modules/economyUtils/commands/revokeCurrency.js +28 -0
  94. package/dist/modules/economyUtils/commands/revokeCurrency.js.map +1 -0
  95. package/dist/modules/economyUtils/commands/shop.d.ts +2 -0
  96. package/dist/modules/economyUtils/commands/shop.d.ts.map +1 -0
  97. package/dist/modules/economyUtils/commands/shop.js +69 -0
  98. package/dist/modules/economyUtils/commands/shop.js.map +1 -0
  99. package/dist/modules/economyUtils/commands/topCurrency.d.ts +2 -0
  100. package/dist/modules/economyUtils/commands/topCurrency.d.ts.map +1 -0
  101. package/dist/modules/economyUtils/commands/topCurrency.js +22 -0
  102. package/dist/modules/economyUtils/commands/topCurrency.js.map +1 -0
  103. package/dist/modules/economyUtils/commands/transfer.d.ts +2 -0
  104. package/dist/modules/economyUtils/commands/transfer.d.ts.map +1 -0
  105. package/dist/modules/economyUtils/commands/transfer.js +55 -0
  106. package/dist/modules/economyUtils/commands/transfer.js.map +1 -0
  107. package/dist/modules/economyUtils/cronJobs/zombieKillReward.d.ts +2 -0
  108. package/dist/modules/economyUtils/cronJobs/zombieKillReward.d.ts.map +1 -0
  109. package/dist/modules/economyUtils/cronJobs/zombieKillReward.js +66 -0
  110. package/dist/modules/economyUtils/cronJobs/zombieKillReward.js.map +1 -0
  111. package/dist/modules/economyUtils/index.d.ts +5 -0
  112. package/dist/modules/economyUtils/index.d.ts.map +1 -0
  113. package/dist/modules/economyUtils/index.js +192 -0
  114. package/dist/modules/economyUtils/index.js.map +1 -0
  115. package/dist/modules/geoBlock/hooks/IPDetected.d.ts +2 -0
  116. package/dist/modules/geoBlock/hooks/IPDetected.d.ts.map +1 -0
  117. package/dist/modules/geoBlock/hooks/IPDetected.js +50 -0
  118. package/dist/modules/geoBlock/hooks/IPDetected.js.map +1 -0
  119. package/dist/modules/geoBlock/index.d.ts +9 -0
  120. package/dist/modules/geoBlock/index.d.ts.map +1 -0
  121. package/dist/modules/geoBlock/index.js +329 -0
  122. package/dist/modules/geoBlock/index.js.map +1 -0
  123. package/dist/modules/gimme/commands/gimme.d.ts +2 -0
  124. package/dist/modules/gimme/commands/gimme.d.ts.map +1 -0
  125. package/dist/modules/gimme/commands/gimme.js +25 -0
  126. package/dist/modules/gimme/commands/gimme.js.map +1 -0
  127. package/dist/modules/gimme/index.d.ts +5 -0
  128. package/dist/modules/gimme/index.d.ts.map +1 -0
  129. package/dist/modules/gimme/index.js +75 -0
  130. package/dist/modules/gimme/index.js.map +1 -0
  131. package/dist/modules/highPingKicker/cronJobs/Ping check.d.ts +2 -0
  132. package/dist/modules/highPingKicker/cronJobs/Ping check.d.ts.map +1 -0
  133. package/dist/modules/highPingKicker/cronJobs/Ping check.js +59 -0
  134. package/dist/modules/highPingKicker/cronJobs/Ping check.js.map +1 -0
  135. package/dist/modules/highPingKicker/index.d.ts +5 -0
  136. package/dist/modules/highPingKicker/index.d.ts.map +1 -0
  137. package/dist/modules/highPingKicker/index.js +44 -0
  138. package/dist/modules/highPingKicker/index.js.map +1 -0
  139. package/dist/modules/lottery/commands/buyTicket.d.ts +2 -0
  140. package/dist/modules/lottery/commands/buyTicket.d.ts.map +1 -0
  141. package/dist/modules/lottery/commands/buyTicket.js +51 -0
  142. package/dist/modules/lottery/commands/buyTicket.js.map +1 -0
  143. package/dist/modules/lottery/commands/nextDraw.d.ts +2 -0
  144. package/dist/modules/lottery/commands/nextDraw.d.ts.map +1 -0
  145. package/dist/modules/lottery/commands/nextDraw.js +34 -0
  146. package/dist/modules/lottery/commands/nextDraw.js.map +1 -0
  147. package/dist/modules/lottery/commands/viewTickets.d.ts +2 -0
  148. package/dist/modules/lottery/commands/viewTickets.d.ts.map +1 -0
  149. package/dist/modules/lottery/commands/viewTickets.js +20 -0
  150. package/dist/modules/lottery/commands/viewTickets.js.map +1 -0
  151. package/dist/modules/lottery/cronJobs/drawLottery.d.ts +2 -0
  152. package/dist/modules/lottery/cronJobs/drawLottery.d.ts.map +1 -0
  153. package/dist/modules/lottery/cronJobs/drawLottery.js +96 -0
  154. package/dist/modules/lottery/cronJobs/drawLottery.js.map +1 -0
  155. package/dist/modules/lottery/index.d.ts +5 -0
  156. package/dist/modules/lottery/index.d.ts.map +1 -0
  157. package/dist/modules/lottery/index.js +85 -0
  158. package/dist/modules/lottery/index.js.map +1 -0
  159. package/dist/modules/playerOnboarding/commands/starterkit.d.ts +2 -0
  160. package/dist/modules/playerOnboarding/commands/starterkit.d.ts.map +1 -0
  161. package/dist/modules/playerOnboarding/commands/starterkit.js +47 -0
  162. package/dist/modules/playerOnboarding/commands/starterkit.js.map +1 -0
  163. package/dist/modules/playerOnboarding/hooks/playerConnected.d.ts +2 -0
  164. package/dist/modules/playerOnboarding/hooks/playerConnected.d.ts.map +1 -0
  165. package/dist/modules/playerOnboarding/hooks/playerConnected.js +11 -0
  166. package/dist/modules/playerOnboarding/hooks/playerConnected.js.map +1 -0
  167. package/dist/modules/playerOnboarding/index.d.ts +5 -0
  168. package/dist/modules/playerOnboarding/index.d.ts.map +1 -0
  169. package/dist/modules/playerOnboarding/index.js +83 -0
  170. package/dist/modules/playerOnboarding/index.js.map +1 -0
  171. package/dist/modules/serverMessages/cronJobs/Automated message.d.ts +2 -0
  172. package/dist/modules/serverMessages/cronJobs/Automated message.d.ts.map +1 -0
  173. package/dist/modules/serverMessages/cronJobs/Automated message.js +41 -0
  174. package/dist/modules/serverMessages/cronJobs/Automated message.js.map +1 -0
  175. package/dist/modules/serverMessages/index.d.ts +5 -0
  176. package/dist/modules/serverMessages/index.d.ts.map +1 -0
  177. package/dist/modules/serverMessages/index.js +45 -0
  178. package/dist/modules/serverMessages/index.js.map +1 -0
  179. package/dist/modules/teleports/commands/deletetp.d.ts +2 -0
  180. package/dist/modules/teleports/commands/deletetp.d.ts.map +1 -0
  181. package/dist/modules/teleports/commands/deletetp.js +20 -0
  182. package/dist/modules/teleports/commands/deletetp.js.map +1 -0
  183. package/dist/modules/teleports/commands/deletewaypoint.d.ts +2 -0
  184. package/dist/modules/teleports/commands/deletewaypoint.d.ts.map +1 -0
  185. package/dist/modules/teleports/commands/deletewaypoint.js +20 -0
  186. package/dist/modules/teleports/commands/deletewaypoint.js.map +1 -0
  187. package/dist/modules/teleports/commands/listwaypoints.d.ts +2 -0
  188. package/dist/modules/teleports/commands/listwaypoints.d.ts.map +1 -0
  189. package/dist/modules/teleports/commands/listwaypoints.js +17 -0
  190. package/dist/modules/teleports/commands/listwaypoints.js.map +1 -0
  191. package/dist/modules/teleports/commands/setprivate.d.ts +2 -0
  192. package/dist/modules/teleports/commands/setprivate.d.ts.map +1 -0
  193. package/dist/modules/teleports/commands/setprivate.js +29 -0
  194. package/dist/modules/teleports/commands/setprivate.js.map +1 -0
  195. package/dist/modules/teleports/commands/setpublic.d.ts +2 -0
  196. package/dist/modules/teleports/commands/setpublic.d.ts.map +1 -0
  197. package/dist/modules/teleports/commands/setpublic.js +45 -0
  198. package/dist/modules/teleports/commands/setpublic.js.map +1 -0
  199. package/dist/modules/teleports/commands/settp.d.ts +2 -0
  200. package/dist/modules/teleports/commands/settp.d.ts.map +1 -0
  201. package/dist/modules/teleports/commands/settp.js +40 -0
  202. package/dist/modules/teleports/commands/settp.js.map +1 -0
  203. package/dist/modules/teleports/commands/setwaypoint.d.ts +2 -0
  204. package/dist/modules/teleports/commands/setwaypoint.d.ts.map +1 -0
  205. package/dist/modules/teleports/commands/setwaypoint.js +28 -0
  206. package/dist/modules/teleports/commands/setwaypoint.js.map +1 -0
  207. package/dist/modules/teleports/commands/teleport.d.ts +2 -0
  208. package/dist/modules/teleports/commands/teleport.d.ts.map +1 -0
  209. package/dist/modules/teleports/commands/teleport.js +68 -0
  210. package/dist/modules/teleports/commands/teleport.js.map +1 -0
  211. package/dist/modules/teleports/commands/teleportwaypoint.d.ts +2 -0
  212. package/dist/modules/teleports/commands/teleportwaypoint.d.ts.map +1 -0
  213. package/dist/modules/teleports/commands/teleportwaypoint.js +43 -0
  214. package/dist/modules/teleports/commands/teleportwaypoint.js.map +1 -0
  215. package/dist/modules/teleports/commands/tplist.d.ts +2 -0
  216. package/dist/modules/teleports/commands/tplist.d.ts.map +1 -0
  217. package/dist/modules/teleports/commands/tplist.js +46 -0
  218. package/dist/modules/teleports/commands/tplist.js.map +1 -0
  219. package/dist/modules/teleports/cronJobs/Waypoint reconciler.d.ts +2 -0
  220. package/dist/modules/teleports/cronJobs/Waypoint reconciler.d.ts.map +1 -0
  221. package/dist/modules/teleports/cronJobs/Waypoint reconciler.js +6 -0
  222. package/dist/modules/teleports/cronJobs/Waypoint reconciler.js.map +1 -0
  223. package/dist/modules/teleports/functions/utils.d.ts +14 -0
  224. package/dist/modules/teleports/functions/utils.d.ts.map +1 -0
  225. package/dist/modules/teleports/functions/utils.js +156 -0
  226. package/dist/modules/teleports/functions/utils.js.map +1 -0
  227. package/dist/modules/teleports/index.d.ts +5 -0
  228. package/dist/modules/teleports/index.d.ts.map +1 -0
  229. package/dist/modules/teleports/index.js +208 -0
  230. package/dist/modules/teleports/index.js.map +1 -0
  231. package/dist/modules/timedShutdown/cronJobs/Shutdown.d.ts +2 -0
  232. package/dist/modules/timedShutdown/cronJobs/Shutdown.d.ts.map +1 -0
  233. package/dist/modules/timedShutdown/cronJobs/Shutdown.js +7 -0
  234. package/dist/modules/timedShutdown/cronJobs/Shutdown.js.map +1 -0
  235. package/dist/modules/timedShutdown/cronJobs/warning.d.ts +2 -0
  236. package/dist/modules/timedShutdown/cronJobs/warning.d.ts.map +1 -0
  237. package/dist/modules/timedShutdown/cronJobs/warning.js +10 -0
  238. package/dist/modules/timedShutdown/cronJobs/warning.js.map +1 -0
  239. package/dist/modules/timedShutdown/index.d.ts +5 -0
  240. package/dist/modules/timedShutdown/index.d.ts.map +1 -0
  241. package/dist/modules/timedShutdown/index.js +43 -0
  242. package/dist/modules/timedShutdown/index.js.map +1 -0
  243. package/dist/modules/utils/commands/help.d.ts +2 -0
  244. package/dist/modules/utils/commands/help.d.ts.map +1 -0
  245. package/dist/modules/utils/commands/help.js +84 -0
  246. package/dist/modules/utils/commands/help.js.map +1 -0
  247. package/dist/modules/utils/commands/ping.d.ts +2 -0
  248. package/dist/modules/utils/commands/ping.d.ts.map +1 -0
  249. package/dist/modules/utils/commands/ping.js +6 -0
  250. package/dist/modules/utils/commands/ping.js.map +1 -0
  251. package/dist/modules/utils/index.d.ts +5 -0
  252. package/dist/modules/utils/index.d.ts.map +1 -0
  253. package/dist/modules/utils/index.js +52 -0
  254. package/dist/modules/utils/index.js.map +1 -0
  255. package/dist/modules.json +757 -0
  256. package/package.json +26 -0
  257. package/scripts/buildBuiltinJson.ts +81 -0
  258. package/src/BuiltinModule.ts +159 -0
  259. package/src/__tests__/aliases.integration.test.ts +90 -0
  260. package/src/__tests__/bugRepros.integration.test.ts +485 -0
  261. package/src/__tests__/builtinmodule.unit.test.ts +15 -0
  262. package/src/__tests__/commandArgs.integration.test.ts +291 -0
  263. package/src/__tests__/crossServerPlayer.integration.test.ts +176 -0
  264. package/src/__tests__/defaultSystemConfigAliases.integration.test.ts +215 -0
  265. package/src/__tests__/economy/claim.integration.test.ts +250 -0
  266. package/src/__tests__/economy/economyUtils.integration.test.ts +495 -0
  267. package/src/__tests__/economy/shop.integration.test.ts +177 -0
  268. package/src/__tests__/economy/zombieKillReward.integration.test.ts +293 -0
  269. package/src/__tests__/geoblock.integration.test.ts +322 -0
  270. package/src/__tests__/gimme.integration.test.ts +106 -0
  271. package/src/__tests__/help.integration.test.ts +314 -0
  272. package/src/__tests__/highPingKicker.integration.test.ts +618 -0
  273. package/src/__tests__/lottery.integration.test.ts +344 -0
  274. package/src/__tests__/modulePermission.integration.test.ts +387 -0
  275. package/src/__tests__/onboarding.integration.test.ts +122 -0
  276. package/src/__tests__/ping.integration.test.ts +36 -0
  277. package/src/__tests__/roleExpiry.integration.test.ts +78 -0
  278. package/src/__tests__/serverMessages.integration.test.ts +116 -0
  279. package/src/__tests__/systemConfigCooldown.integration.test.ts +84 -0
  280. package/src/__tests__/systemConfigCost.integration.test.ts +194 -0
  281. package/src/__tests__/teleports/listtp.integration.test.ts +189 -0
  282. package/src/__tests__/teleports/publicteleports.integration.test.ts +345 -0
  283. package/src/__tests__/teleports/teleport.integration.test.ts +153 -0
  284. package/src/__tests__/teleports/tpManagement.integration.test.ts +175 -0
  285. package/src/__tests__/teleports/waypoints.integration.test.ts +832 -0
  286. package/src/community-modules/README.md +5 -0
  287. package/src/community-modules/modules/vote.json +19 -0
  288. package/src/dto/base.ts +13 -0
  289. package/src/dto/discordEvents.ts +69 -0
  290. package/src/dto/gameEvents.ts +159 -0
  291. package/src/dto/index.ts +25 -0
  292. package/src/dto/takaroEvents.ts +525 -0
  293. package/src/main.ts +47 -0
  294. package/src/modules/chatBridge/hooks/DiscordToGame.js +18 -0
  295. package/src/modules/chatBridge/hooks/GameToDiscord.js +18 -0
  296. package/src/modules/chatBridge/hooks/PlayerConnected.js +11 -0
  297. package/src/modules/chatBridge/hooks/PlayerDisconnected.js +11 -0
  298. package/src/modules/chatBridge/index.ts +64 -0
  299. package/src/modules/dailyRewards/commands/daily.js +114 -0
  300. package/src/modules/dailyRewards/commands/streak.js +42 -0
  301. package/src/modules/dailyRewards/commands/topstreak.js +54 -0
  302. package/src/modules/dailyRewards/functions/utils.js +36 -0
  303. package/src/modules/dailyRewards/hooks/dailyLoginCheck.js +24 -0
  304. package/src/modules/dailyRewards/index.ts +138 -0
  305. package/src/modules/economyUtils/commands/balance.js +8 -0
  306. package/src/modules/economyUtils/commands/claim.js +42 -0
  307. package/src/modules/economyUtils/commands/confirmTransfer.js +55 -0
  308. package/src/modules/economyUtils/commands/grantCurrency.js +34 -0
  309. package/src/modules/economyUtils/commands/revokeCurrency.js +34 -0
  310. package/src/modules/economyUtils/commands/shop.js +87 -0
  311. package/src/modules/economyUtils/commands/topCurrency.js +29 -0
  312. package/src/modules/economyUtils/commands/transfer.js +73 -0
  313. package/src/modules/economyUtils/cronJobs/zombieKillReward.js +82 -0
  314. package/src/modules/economyUtils/index.ts +197 -0
  315. package/src/modules/geoBlock/hooks/IPDetected.js +53 -0
  316. package/src/modules/geoBlock/index.ts +333 -0
  317. package/src/modules/gimme/commands/gimme.js +30 -0
  318. package/src/modules/gimme/index.ts +76 -0
  319. package/src/modules/highPingKicker/cronJobs/Ping check.js +68 -0
  320. package/src/modules/highPingKicker/index.ts +44 -0
  321. package/src/modules/lottery/commands/buyTicket.js +64 -0
  322. package/src/modules/lottery/commands/nextDraw.js +47 -0
  323. package/src/modules/lottery/commands/viewTickets.js +28 -0
  324. package/src/modules/lottery/cronJobs/drawLottery.js +124 -0
  325. package/src/modules/lottery/index.ts +86 -0
  326. package/src/modules/playerOnboarding/commands/starterkit.js +61 -0
  327. package/src/modules/playerOnboarding/hooks/playerConnected.js +14 -0
  328. package/src/modules/playerOnboarding/index.ts +86 -0
  329. package/src/modules/serverMessages/cronJobs/Automated message.js +47 -0
  330. package/src/modules/serverMessages/index.ts +46 -0
  331. package/src/modules/teleports/commands/deletetp.js +25 -0
  332. package/src/modules/teleports/commands/deletewaypoint.js +24 -0
  333. package/src/modules/teleports/commands/listwaypoints.js +23 -0
  334. package/src/modules/teleports/commands/setprivate.js +39 -0
  335. package/src/modules/teleports/commands/setpublic.js +60 -0
  336. package/src/modules/teleports/commands/settp.js +50 -0
  337. package/src/modules/teleports/commands/setwaypoint.js +31 -0
  338. package/src/modules/teleports/commands/teleport.js +84 -0
  339. package/src/modules/teleports/commands/teleportwaypoint.js +57 -0
  340. package/src/modules/teleports/commands/tplist.js +62 -0
  341. package/src/modules/teleports/cronJobs/Waypoint reconciler.js +7 -0
  342. package/src/modules/teleports/functions/utils.js +189 -0
  343. package/src/modules/teleports/index.ts +217 -0
  344. package/src/modules/timedShutdown/cronJobs/Shutdown.js +8 -0
  345. package/src/modules/timedShutdown/cronJobs/warning.js +13 -0
  346. package/src/modules/timedShutdown/index.ts +45 -0
  347. package/src/modules/utils/commands/help.js +100 -0
  348. package/src/modules/utils/commands/ping.js +7 -0
  349. package/src/modules/utils/index.ts +53 -0
  350. package/tsconfig.build.json +14 -0
  351. package/tsconfig.json +9 -0
  352. package/typedoc.json +3 -0
@@ -0,0 +1,757 @@
1
+ [
2
+ {
3
+ "name": "utils",
4
+ "author": "Takaro",
5
+ "supportedGames": [
6
+ "all"
7
+ ],
8
+ "versions": [
9
+ {
10
+ "tag": "0.0.2",
11
+ "description": "A collection of useful commands",
12
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"additionalProperties\":false}",
13
+ "commands": [
14
+ {
15
+ "function": "import { data } from '@takaro/helpers';\nasync function main() {\n await data.player.pm('Pong!');\n}\nawait main();\n//# sourceMappingURL=ping.js.map",
16
+ "name": "ping",
17
+ "trigger": "ping",
18
+ "helpText": "Replies with pong, useful for testing if the connection works.",
19
+ "arguments": []
20
+ },
21
+ {
22
+ "function": "import { data, takaro, TakaroUserError, checkPermission } from '@takaro/helpers';\nasync function main() {\n const enabledModules = await takaro.module.moduleInstallationsControllerGetInstalledModules({\n filters: { gameserverId: [data.gameServerId] },\n });\n const moduleCommands = await Promise.all(enabledModules.data.data.map(async (mod) => {\n // Check if the module itself is enabled\n if (!mod.systemConfig.enabled) {\n return [];\n }\n const installedVersion = await takaro.module.moduleVersionControllerGetModuleVersion(mod.versionId);\n const commands = installedVersion.data.data.commands;\n // Filter out disabled commands\n return commands.filter((command) => {\n const commandConfig = mod.systemConfig.commands && mod.systemConfig.commands[command.name];\n return commandConfig && commandConfig.enabled;\n });\n }));\n const allCommandsFlat = moduleCommands.flat();\n // Filter commands based on player permissions\n const accessibleCommands = allCommandsFlat.filter((command) => {\n // If command has no required permissions, it's accessible to all\n if (!command.requiredPermissions || command.requiredPermissions.length === 0) {\n return true;\n }\n // Check if player has all required permissions\n return command.requiredPermissions.every((permission) => checkPermission(data.pog, permission));\n });\n if (data.arguments.command === 'search') {\n // Check if a search term was actually provided (not the default 'none')\n if (data.arguments.searchTerm === 'none') {\n throw new TakaroUserError('Please provide a search term. Usage: /help search <term>');\n }\n // Search functionality\n const searchTerm = data.arguments.searchTerm.toLowerCase();\n const matchingCommands = accessibleCommands.filter((command) => {\n // Check if command name contains search term\n const nameMatch = command.name.toLowerCase().includes(searchTerm);\n // Check if help text contains search term\n const helpTextMatch = command.helpText.toLowerCase().includes(searchTerm);\n return nameMatch || helpTextMatch;\n });\n if (matchingCommands.length === 0) {\n await data.player.pm(`No commands found matching \"${data.arguments.searchTerm}\".`);\n }\n else {\n await data.player.pm(`Commands matching \"${data.arguments.searchTerm}\":`);\n await Promise.all(matchingCommands.map(async (command) => {\n await data.player.pm(`${command.name}: ${command.helpText}`);\n }));\n }\n }\n else if (data.arguments.command === 'all') {\n await data.player.pm('Available commands:');\n if (accessibleCommands.length === 0) {\n await data.player.pm('No commands available to you.');\n }\n else {\n await Promise.all(accessibleCommands.map(async (command) => {\n await data.player.pm(`${command.name}: ${command.helpText}`);\n }));\n }\n }\n else {\n const requestedCommand = allCommandsFlat.find((c) => {\n return c.name === data.arguments.command;\n });\n if (!requestedCommand) {\n throw new TakaroUserError(`Unknown command \"${data.arguments.command}\", use this command without arguments to see all available commands.`);\n }\n else {\n // Check if player has permission to use this command\n const hasAccess = !requestedCommand.requiredPermissions ||\n requestedCommand.requiredPermissions.length === 0 ||\n requestedCommand.requiredPermissions.every((permission) => checkPermission(data.pog, permission));\n if (!hasAccess) {\n throw new TakaroUserError(`You don't have permission to use the \"${data.arguments.command}\" command.`);\n }\n await data.player.pm(`${requestedCommand.name}: ${requestedCommand.helpText}`);\n }\n }\n}\nawait main();\n//# sourceMappingURL=help.js.map",
23
+ "name": "help",
24
+ "trigger": "help",
25
+ "helpText": "The text you are reading right now, displays information about commands.",
26
+ "arguments": [
27
+ {
28
+ "name": "command",
29
+ "type": "string",
30
+ "defaultValue": "all",
31
+ "helpText": "The command to get help for, or \"search\" to search for commands",
32
+ "position": 0
33
+ },
34
+ {
35
+ "name": "searchTerm",
36
+ "type": "string",
37
+ "defaultValue": "none",
38
+ "helpText": "Search term to find commands (when first argument is \"search\")",
39
+ "position": 1
40
+ }
41
+ ]
42
+ }
43
+ ]
44
+ }
45
+ ]
46
+ },
47
+ {
48
+ "name": "teleports",
49
+ "author": "Takaro",
50
+ "supportedGames": [
51
+ "7 days to die",
52
+ "rust",
53
+ "minecraft"
54
+ ],
55
+ "versions": [
56
+ {
57
+ "tag": "0.0.4",
58
+ "description": "A set of commands to allow players to set their own teleport points and teleport to them.",
59
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"timeout\":{\"title\":\"Timeout\",\"description\":\"The time one has to wait before teleporting again.\",\"x-component\":\"duration\",\"type\":\"number\",\"minimum\":0,\"default\":1000},\"allowPublicTeleports\":{\"type\":\"boolean\",\"description\":\"Players can create public teleports.\",\"default\":false}},\"required\":[],\"additionalProperties\":false}",
60
+ "uiSchema": "{\"timeout\":{\"ui:widget\":\"duration\"}}",
61
+ "functions": [
62
+ {
63
+ "name": "utils",
64
+ "function": "import { takaro, data } from '@takaro/helpers';\nexport function getVariableKey(tpName, pub = false) {\n if (pub && tpName)\n return `pubtp_${tpName}`;\n if (pub && !tpName)\n return 'pubtp_';\n if (tpName)\n return `tp_${tpName}`;\n return 'tp_';\n}\nexport async function findTp(tpName, playerId, pub = false) {\n const { gameServerId, module: mod } = data;\n if (pub) {\n return takaro.variable.variableControllerSearch({\n filters: {\n key: [getVariableKey(tpName, true)],\n gameServerId: [gameServerId],\n playerId: [playerId].filter(Boolean),\n moduleId: [mod.moduleId],\n },\n sortBy: 'key',\n sortDirection: 'asc',\n });\n }\n return takaro.variable.variableControllerSearch({\n filters: {\n key: [getVariableKey(tpName)],\n gameServerId: [gameServerId],\n playerId: [playerId].filter(Boolean),\n moduleId: [mod.moduleId],\n },\n sortBy: 'key',\n sortDirection: 'asc',\n });\n}\nexport async function ensureWaypointsModule() {\n const { gameServerId } = data;\n let waypointsDefinition = (await takaro.module.moduleControllerSearch({\n filters: {\n name: ['Waypoints'],\n },\n })).data.data[0];\n if (!waypointsDefinition) {\n console.log('Waypoints module definition not found, creating it.');\n waypointsDefinition = (await takaro.module.moduleControllerCreate({\n name: 'Waypoints',\n })).data.data;\n }\n let waypointsInstallation = (await takaro.module.moduleInstallationsControllerGetInstalledModules({\n filters: { gameserverId: [gameServerId] },\n })).data.data.find((module) => module.module.name === 'Waypoints');\n if (!waypointsInstallation) {\n console.log('Waypoints installation not found, installing it.');\n waypointsInstallation = (await takaro.module.moduleInstallationsControllerInstallModule({\n gameServerId,\n versionId: waypointsDefinition.latestVersion.id,\n })).data.data;\n }\n return { waypointsInstallation, waypointsDefinition };\n}\nexport function getWaypointName(name) {\n return `waypoint ${name}`;\n}\nexport function getWaypointId(varName) {\n const split = varName.split(' ')[1];\n if (split)\n return split;\n return varName;\n}\n/**\n * This function is responsible to read all the configured waypoints (vars)\n * and then ensuring that the waypoints module has the correct config\n */\nexport async function waypointReconciler() {\n console.log('Reconciling waypoints');\n const { waypointsInstallation, waypointsDefinition } = await ensureWaypointsModule();\n const { gameServerId, module: mod } = data;\n // Get all the installed waypoints\n const waypointVars = (await takaro.variable.variableControllerSearch({\n filters: {\n moduleId: [mod.moduleId],\n gameServerId: [gameServerId],\n },\n search: {\n key: [getWaypointName('')],\n },\n })).data.data;\n const waypointsInModule = waypointsDefinition.latestVersion.commands;\n // Check if any waypoints are missing in module\n const missingWaypoints = waypointVars.filter((waypointVar) => {\n const existingWaypointsForServer = waypointsInModule.filter((waypoint) => waypoint.name.includes(gameServerId));\n return !existingWaypointsForServer.some((waypoint) => waypoint.trigger === getWaypointId(waypointVar.key));\n });\n // Check if there are waypoints too many in module compared to our vars\n const toDeleteWaypoints = waypointsInModule.filter((waypoint) => {\n // We ignore any commands that are not for this game server\n if (!waypoint.name.includes(gameServerId))\n return false;\n return !waypointVars.some((waypointVar) => getWaypointId(waypointVar.key) === waypoint.trigger);\n });\n if (!missingWaypoints.length && !toDeleteWaypoints.length) {\n // No changes in waypoints, exit\n return;\n }\n console.log('Missing waypoints:', missingWaypoints.map((waypoint) => waypoint.key));\n console.log('To delete waypoints:', toDeleteWaypoints.map((waypoint) => waypoint.trigger));\n // Fetch the teleporting code template\n const teleportCommand = await takaro.command.commandControllerSearch({\n filters: {\n moduleId: [mod.moduleId],\n name: ['teleportwaypoint'],\n },\n });\n // Edit the module accordingly\n await Promise.all([\n ...missingWaypoints.map((waypoint) => {\n return takaro.command.commandControllerCreate({\n name: `waypoint ${getWaypointId(waypoint.key)} server ${gameServerId}`,\n trigger: getWaypointId(waypoint.key),\n helpText: `Teleport to waypoint ${getWaypointId(waypoint.key)}.`,\n function: teleportCommand.data.data[0].function.code,\n versionId: waypointsInstallation.versionId,\n });\n }),\n ...toDeleteWaypoints.map((waypointVar) => {\n return takaro.command.commandControllerRemove(waypointVar.id);\n }),\n ]);\n // Update permissions\n const existingPermissions = waypointsDefinition.latestVersion.permissions || [];\n const permissionInputDTOs = existingPermissions.map((permission) => ({\n permission: permission.permission,\n description: permission.description,\n friendlyName: permission.friendlyName,\n canHaveCount: permission.canHaveCount,\n }));\n // We need to filter out the permissions we deleted in the above lines\n const filteredPermissionsInputs = permissionInputDTOs.filter((permission) => {\n return !toDeleteWaypoints.some((waypoint) => permission.permission === `WAYPOINTS_USE_${waypoint.trigger.toUpperCase()}_${gameServerId}`);\n });\n const gameServer = (await takaro.gameserver.gameServerControllerGetOne(gameServerId)).data.data;\n await takaro.module.moduleControllerUpdate(waypointsInstallation.moduleId, {\n latestVersion: {\n permissions: [\n ...filteredPermissionsInputs,\n ...missingWaypoints.map((waypoint) => ({\n permission: `WAYPOINTS_USE_${getWaypointId(waypoint.key).toUpperCase()}_${gameServerId}`,\n description: `Use the waypoint ${getWaypointId(waypoint.key)} on ${gameServer.name}.`,\n friendlyName: `Use waypoint ${getWaypointId(waypoint.key)} on ${gameServer.name}`,\n canHaveCount: false,\n })),\n ],\n },\n });\n}\n//# sourceMappingURL=utils.js.map"
65
+ }
66
+ ],
67
+ "permissions": [
68
+ {
69
+ "permission": "TELEPORTS_CREATE_PUBLIC",
70
+ "friendlyName": "Create Public Teleports",
71
+ "description": "Allows the player to create public teleports.",
72
+ "canHaveCount": true
73
+ },
74
+ {
75
+ "permission": "TELEPORTS_USE",
76
+ "friendlyName": "Use Teleports",
77
+ "description": "Allows the player to use teleports modules.",
78
+ "canHaveCount": true
79
+ },
80
+ {
81
+ "permission": "TELEPORTS_MANAGE_WAYPOINTS",
82
+ "friendlyName": "Manage waypoints",
83
+ "description": "Allows creating, deleting, and managing waypoints.",
84
+ "canHaveCount": false
85
+ }
86
+ ],
87
+ "commands": [
88
+ {
89
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nimport { findTp } from './utils.js';\nasync function main() {\n const { pog, gameServerId, arguments: args, module: mod } = data;\n const ownedTeleportRes = await findTp(args.tp, pog.playerId);\n let teleports = ownedTeleportRes.data.data;\n if (mod.userConfig.allowPublicTeleports) {\n const publicTeleportRes = await findTp(args.tp, null, true);\n teleports = teleports.concat(publicTeleportRes.data.data);\n }\n if (teleports.length === 0) {\n throw new TakaroUserError(`Teleport ${args.tp} does not exist.`);\n }\n const timeout = mod.userConfig.timeout;\n if (timeout > 0) {\n const lastExecuted = await takaro.variable.variableControllerSearch({\n filters: {\n key: ['lastExecuted'],\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n });\n let lastExecutedRecord = lastExecuted.data.data[0];\n if (!lastExecutedRecord) {\n const createRes = await takaro.variable.variableControllerCreate({\n key: 'lastExecuted',\n gameServerId,\n playerId: pog.playerId,\n moduleId: mod.moduleId,\n value: new Date().toISOString(),\n });\n lastExecutedRecord = createRes.data.data;\n }\n else {\n const lastExecutedTime = new Date(lastExecutedRecord.value);\n const now = new Date();\n const diff = now.getTime() - lastExecutedTime.getTime();\n if (diff < timeout) {\n throw new TakaroUserError('You cannot teleport yet. Please wait before trying again.');\n }\n }\n const teleport = JSON.parse(teleports[0].value);\n await takaro.gameserver.gameServerControllerTeleportPlayer(gameServerId, pog.playerId, {\n x: teleport.x,\n y: teleport.y,\n z: teleport.z,\n dimension: teleport.dimension,\n });\n await data.player.pm(`Teleported to ${teleport.name}.`);\n if (timeout !== 0 && lastExecutedRecord) {\n await takaro.variable.variableControllerUpdate(lastExecutedRecord.id, {\n value: new Date().toISOString(),\n });\n }\n return;\n }\n const teleport = JSON.parse(teleports[0].value);\n await takaro.gameserver.gameServerControllerTeleportPlayer(gameServerId, pog.playerId, {\n x: teleport.x,\n y: teleport.y,\n z: teleport.z,\n dimension: teleport.dimension,\n });\n await data.player.pm(`Teleported to ${teleport.name}.`);\n}\nawait main();\n//# sourceMappingURL=teleport.js.map",
90
+ "name": "teleport",
91
+ "trigger": "tp",
92
+ "helpText": "Teleports to one of your set locations.",
93
+ "requiredPermissions": [
94
+ "TELEPORTS_USE"
95
+ ],
96
+ "arguments": [
97
+ {
98
+ "name": "tp",
99
+ "type": "string",
100
+ "defaultValue": null,
101
+ "helpText": "The location to teleport to.",
102
+ "position": 0
103
+ }
104
+ ]
105
+ },
106
+ {
107
+ "function": "import { takaro, data } from '@takaro/helpers';\nimport { getVariableKey } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n const ownedTeleports = (await takaro.variable.variableControllerSearch({\n filters: {\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n search: {\n key: [getVariableKey(undefined, false)],\n },\n sortBy: 'key',\n sortDirection: 'asc',\n })).data.data;\n const publicTeleports = (await takaro.variable.variableControllerSearch({\n filters: {\n gameServerId: [gameServerId],\n moduleId: [mod.moduleId],\n },\n search: {\n key: [getVariableKey(undefined, true)],\n },\n sortBy: 'key',\n sortDirection: 'asc',\n })).data.data\n // Filter out public teleports that are owned by the player\n // Since we'll be showing them in the owned teleports list\n .filter((teleport) => {\n return teleport.playerId !== pog.playerId;\n });\n const teleports = [...ownedTeleports, ...publicTeleports];\n if (teleports.length === 0) {\n await data.player.pm(`You have no teleports available, use ${prefix}settp <name> to set one.`);\n return;\n }\n await data.player.pm(`You have ${teleports.length} teleport${teleports.length === 1 ? '' : 's'} available`);\n for (const rawTeleport of teleports) {\n const teleport = JSON.parse(rawTeleport.value);\n await data.player.pm(`${teleport.name}: (${teleport.x},${teleport.y},${teleport.z}) ${rawTeleport.key.startsWith('pub') ? '(public)' : ''}`);\n }\n}\nawait main();\n//# sourceMappingURL=tplist.js.map",
108
+ "name": "tplist",
109
+ "trigger": "tplist",
110
+ "helpText": "Lists all your set locations.",
111
+ "requiredPermissions": [
112
+ "TELEPORTS_USE"
113
+ ],
114
+ "arguments": []
115
+ },
116
+ {
117
+ "function": "import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';\nimport { getVariableKey, findTp } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod, arguments: args } = data;\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n const existingVariable = await findTp(args.tp, pog.playerId);\n if (existingVariable.data.data.length > 0) {\n throw new TakaroUserError(`Teleport ${args.tp} already exists, use ${prefix}deletetp ${args.tp} to delete it.`);\n }\n const hasPermission = checkPermission(pog, 'TELEPORTS_USE');\n const allPlayerTeleports = await takaro.variable.variableControllerSearch({\n search: {\n key: [getVariableKey(undefined), getVariableKey(undefined, true)],\n },\n filters: {\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n });\n if (allPlayerTeleports.data.data.length >= hasPermission.count) {\n throw new TakaroUserError(`You have reached the maximum number of teleports for your role, maximum allowed is ${hasPermission.count}`);\n }\n await takaro.variable.variableControllerCreate({\n key: getVariableKey(args.tp),\n value: JSON.stringify({\n name: args.tp,\n x: data.pog.positionX,\n y: data.pog.positionY,\n z: data.pog.positionZ,\n dimension: data.pog.dimension,\n }),\n gameServerId,\n moduleId: mod.moduleId,\n playerId: pog.playerId,\n });\n await data.player.pm(`Teleport ${args.tp} set.`);\n}\nawait main();\n//# sourceMappingURL=settp.js.map",
118
+ "name": "settp",
119
+ "trigger": "settp",
120
+ "helpText": "Sets a location to teleport to.",
121
+ "requiredPermissions": [
122
+ "TELEPORTS_USE"
123
+ ],
124
+ "arguments": [
125
+ {
126
+ "name": "tp",
127
+ "type": "string",
128
+ "defaultValue": null,
129
+ "helpText": "The location name.",
130
+ "position": 0
131
+ }
132
+ ]
133
+ },
134
+ {
135
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nimport { getVariableKey } from './utils.js';\nasync function main() {\n const { pog, gameServerId, arguments: args, module: mod } = data;\n const existingVariable = await takaro.variable.variableControllerSearch({\n filters: {\n key: [getVariableKey(args.tp), getVariableKey(args.tp, true)],\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n });\n if (existingVariable.data.data.length === 0) {\n throw new TakaroUserError(`Teleport ${args.tp} does not exist.`);\n }\n await takaro.variable.variableControllerDelete(existingVariable.data.data[0].id);\n await data.player.pm(`Teleport ${args.tp} deleted.`);\n}\nawait main();\n//# sourceMappingURL=deletetp.js.map",
136
+ "name": "deletetp",
137
+ "trigger": "deletetp",
138
+ "helpText": "Deletes a location.",
139
+ "arguments": [
140
+ {
141
+ "name": "tp",
142
+ "type": "string",
143
+ "defaultValue": null,
144
+ "helpText": "The location name.",
145
+ "position": 0
146
+ }
147
+ ]
148
+ },
149
+ {
150
+ "function": "import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';\nimport { getVariableKey } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod, arguments: args } = data;\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n if (!mod.userConfig.allowPublicTeleports) {\n throw new TakaroUserError('Public teleports are disabled.');\n }\n const hasPermission = checkPermission(pog, 'TELEPORTS_CREATE_PUBLIC');\n const existingPublicTeleportsForPlayerRes = await takaro.variable.variableControllerSearch({\n search: {\n key: ['pubtp_'],\n },\n filters: {\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n });\n if (existingPublicTeleportsForPlayerRes.data.data.length >= hasPermission.count) {\n throw new TakaroUserError(`You have reached the maximum number of public teleports for your role, maximum allowed is ${hasPermission.count}`);\n }\n const teleports = (await takaro.variable.variableControllerSearch({\n filters: {\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n key: [getVariableKey(args.tp)],\n },\n sortBy: 'key',\n sortDirection: 'asc',\n })).data.data;\n if (teleports.length === 0) {\n throw new TakaroUserError(`No teleport with name ${args.tp} found, use ${prefix}settp <name> to set one first.`);\n }\n const teleportRecord = teleports[0];\n const teleport = JSON.parse(teleportRecord.value);\n await takaro.variable.variableControllerUpdate(teleportRecord.id, {\n key: getVariableKey(args.tp, true),\n value: JSON.stringify(teleport),\n });\n await data.player.pm(`Teleport ${args.tp} is now public.`);\n}\nawait main();\n//# sourceMappingURL=setpublic.js.map",
151
+ "name": "setpublic",
152
+ "trigger": "setpublic",
153
+ "helpText": "Sets a teleport to be public, allowing other players to teleport to it.",
154
+ "requiredPermissions": [
155
+ "TELEPORTS_CREATE_PUBLIC"
156
+ ],
157
+ "arguments": [
158
+ {
159
+ "name": "tp",
160
+ "type": "string",
161
+ "defaultValue": null,
162
+ "helpText": "The location name.",
163
+ "position": 0
164
+ }
165
+ ]
166
+ },
167
+ {
168
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nimport { getVariableKey } from './utils.js';\nasync function main() {\n const { pog, gameServerId, arguments: args, module: mod } = data;\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data;\n const teleportRes = await takaro.variable.variableControllerSearch({\n filters: {\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n key: [getVariableKey(args.tp, true)],\n moduleId: [mod.moduleId],\n },\n sortBy: 'key',\n sortDirection: 'asc',\n });\n const teleports = teleportRes.data.data;\n if (teleports.length === 0) {\n throw new TakaroUserError(`No public teleport with name ${args.tp} found, use ${prefix}settp <name> to set one first.`);\n }\n const teleportRecord = teleports[0];\n const teleport = JSON.parse(teleportRecord.value);\n await takaro.variable.variableControllerUpdate(teleportRecord.id, {\n key: getVariableKey(args.tp),\n value: JSON.stringify(teleport),\n });\n await data.player.pm(`Teleport ${args.tp} is now private.`);\n}\nawait main();\n//# sourceMappingURL=setprivate.js.map",
169
+ "name": "setprivate",
170
+ "trigger": "setprivate",
171
+ "helpText": "Sets a teleport to be private, only the teleport owner can teleport to it.",
172
+ "arguments": [
173
+ {
174
+ "name": "tp",
175
+ "type": "string",
176
+ "defaultValue": null,
177
+ "helpText": "The location name.",
178
+ "position": 0
179
+ }
180
+ ]
181
+ },
182
+ {
183
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nimport { getWaypointName, waypointReconciler } from './utils.js';\nasync function main() {\n const { pog, gameServerId, arguments: args, module: mod } = data;\n try {\n await takaro.variable.variableControllerCreate({\n moduleId: mod.moduleId,\n gameServerId,\n key: getWaypointName(args.waypoint),\n value: JSON.stringify({\n x: pog.positionX,\n y: pog.positionY,\n z: pog.positionZ,\n dimension: pog.dimension,\n }),\n });\n }\n catch (error) {\n if (error.message === 'Request failed with status code 409') {\n throw new TakaroUserError(`Waypoint ${args.waypoint} already exists.`);\n }\n throw error;\n }\n await waypointReconciler();\n await pog.pm(`Waypoint ${args.waypoint} set.`);\n}\nawait main();\n//# sourceMappingURL=setwaypoint.js.map",
184
+ "name": "setwaypoint",
185
+ "trigger": "setwaypoint",
186
+ "helpText": "Creates a new waypoint.",
187
+ "requiredPermissions": [
188
+ "TELEPORTS_MANAGE_WAYPOINTS"
189
+ ],
190
+ "arguments": [
191
+ {
192
+ "name": "waypoint",
193
+ "type": "string",
194
+ "defaultValue": null,
195
+ "helpText": "The location name.",
196
+ "position": 0
197
+ }
198
+ ]
199
+ },
200
+ {
201
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nimport { getWaypointName, waypointReconciler } from './utils.js';\nasync function main() {\n const { pog, gameServerId, arguments: args, module: mod } = data;\n const variable = await takaro.variable.variableControllerSearch({\n filters: {\n key: [getWaypointName(args.waypoint)],\n gameServerId: [gameServerId],\n moduleId: [mod.moduleId],\n },\n });\n if (!variable.data.data.length) {\n throw new TakaroUserError(`Waypoint ${args.waypoint} doesn't exist.`);\n }\n await takaro.variable.variableControllerDelete(variable.data.data[0].id);\n await waypointReconciler();\n await pog.pm(`Waypoint ${args.waypoint} deleted.`);\n}\nawait main();\n//# sourceMappingURL=deletewaypoint.js.map",
202
+ "name": "deletewaypoint",
203
+ "trigger": "deletewaypoint",
204
+ "helpText": "Deletes a waypoint.",
205
+ "requiredPermissions": [
206
+ "TELEPORTS_MANAGE_WAYPOINTS"
207
+ ],
208
+ "arguments": [
209
+ {
210
+ "name": "waypoint",
211
+ "type": "string",
212
+ "defaultValue": null,
213
+ "helpText": "The location name.",
214
+ "position": 0
215
+ }
216
+ ]
217
+ },
218
+ {
219
+ "function": "import { data, checkPermission } from '@takaro/helpers';\nimport { ensureWaypointsModule } from './utils.js';\nasync function main() {\n const { pog, gameServerId } = data;\n const { waypointsDefinition } = await ensureWaypointsModule();\n const allWaypoints = waypointsDefinition.latestVersion.commands;\n const waypointsWithPermission = allWaypoints\n .filter((waypoint) => checkPermission(pog, `WAYPOINTS_USE_${waypoint.trigger.toUpperCase()}_${gameServerId}`))\n .sort((a, b) => a.trigger.localeCompare(b.trigger));\n if (!waypointsWithPermission.length) {\n await pog.pm('There are no waypoints available.');\n return;\n }\n await pog.pm(`Available waypoints: ${waypointsWithPermission.map((waypoint) => waypoint.trigger).join(', ')}`);\n}\nawait main();\n//# sourceMappingURL=listwaypoints.js.map",
220
+ "name": "listwaypoints",
221
+ "trigger": "waypoints",
222
+ "helpText": "Lists all waypoints.",
223
+ "arguments": []
224
+ },
225
+ {
226
+ "function": "import { takaro, data, TakaroUserError, checkPermission } from '@takaro/helpers';\nfunction getWaypointName(name) {\n return `waypoint ${name}`;\n}\nasync function main() {\n const { pog, gameServerId, trigger, module, itemId } = data;\n const triggeredCommand = module.version.commands.find((command) => command.id === itemId);\n if (!triggeredCommand) {\n throw new Error('Waypoint not found.');\n }\n if (!triggeredCommand.name.includes(`server ${gameServerId}`)) {\n console.log(`Waypoint ${trigger} is not for this server.`);\n return;\n }\n if (!checkPermission(pog, `WAYPOINTS_USE_${trigger.toUpperCase()}_${gameServerId}`)) {\n throw new TakaroUserError(`You are not allowed to use the waypoint ${trigger}.`);\n }\n const teleportsModule = (await takaro.module.moduleControllerSearch({\n filters: {\n builtin: ['teleports'],\n },\n })).data.data[0];\n const variable = await takaro.variable.variableControllerSearch({\n filters: {\n key: [getWaypointName(trigger)],\n gameServerId: [gameServerId],\n moduleId: [teleportsModule.id],\n },\n });\n if (variable.data.data.length === 0) {\n throw new TakaroUserError(`Waypoint ${trigger} does not exist.`);\n }\n const waypoint = JSON.parse(variable.data.data[0].value);\n await takaro.gameserver.gameServerControllerTeleportPlayer(gameServerId, pog.playerId, {\n x: waypoint.x,\n y: waypoint.y,\n z: waypoint.z,\n dimension: waypoint.dimension,\n });\n await pog.pm(`Teleported to waypoint ${trigger}.`);\n}\nawait main();\n//# sourceMappingURL=teleportwaypoint.js.map",
227
+ "name": "teleportwaypoint",
228
+ "trigger": "teleportwaypoint",
229
+ "arguments": [],
230
+ "helpText": "Placeholder command, this will not be used directly. The module will install aliases for this command corresponding to the waypoint names."
231
+ }
232
+ ],
233
+ "cronJobs": [
234
+ {
235
+ "name": "Waypoint reconciler",
236
+ "temporalValue": "*/30 * * * *",
237
+ "function": "import { waypointReconciler } from './utils.js';\nasync function main() {\n await waypointReconciler();\n}\nawait main();\n//# sourceMappingURL=Waypoint%20reconciler.js.map"
238
+ }
239
+ ]
240
+ }
241
+ ]
242
+ },
243
+ {
244
+ "name": "playerOnboarding",
245
+ "author": "Takaro",
246
+ "supportedGames": [
247
+ "all"
248
+ ],
249
+ "versions": [
250
+ {
251
+ "tag": "0.0.3",
252
+ "description": "Collection of functions that are executed when a player joins the server. Helps with onboarding new players, like sending a welcome message. Fixed issue with starterkit item identifiers.",
253
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"message\":{\"title\":\"Message\",\"description\":\"The message to send to the player when they join the server.\",\"type\":\"string\",\"minLength\":1,\"maxLength\":256,\"default\":\"Welcome {player} to the server!\"},\"starterKitItems\":{\"type\":\"array\",\"title\":\"Starter kit items\",\"x-component\":\"item\",\"description\":\"List of items a player will receive when they execute the starterkit command for the first time.\",\"uniqueItems\":true,\"items\":{\"type\":\"object\",\"title\":\"Item\",\"properties\":{\"item\":{\"type\":\"string\",\"title\":\"Item\"},\"amount\":{\"type\":\"number\",\"title\":\"Amount\"},\"quality\":{\"type\":\"string\",\"title\":\"Quality\"}}}}},\"required\":[],\"additionalProperties\":false}",
254
+ "uiSchema": "{\"starterKitItems\":{\"items\":{\"item\":{\"ui:widget\":\"item\"}}}}",
255
+ "hooks": [
256
+ {
257
+ "eventType": "player-connected",
258
+ "name": "playerConnected",
259
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const { player } = data;\n const rawMessage = data.module.userConfig.message;\n const message = rawMessage.replace('{player}', player.name);\n await takaro.gameserver.gameServerControllerSendMessage(data.gameServerId, {\n message,\n });\n}\nawait main();\n//# sourceMappingURL=playerConnected.js.map"
260
+ }
261
+ ],
262
+ "commands": [
263
+ {
264
+ "name": "starterkit",
265
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nconst VARIABLE_KEY = 't_starterkit_lock';\nasync function main() {\n const items = data.module.userConfig.starterKitItems;\n if (!items || items.length === 0) {\n throw new TakaroUserError('No starter kit items configured. Please ask your server administrator to configure this.');\n }\n const starterKitLockRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [VARIABLE_KEY],\n gameServerId: [data.gameServerId],\n playerId: [data.player.id],\n },\n });\n if (starterKitLockRes.data.data.length > 0) {\n throw new TakaroUserError('You already used starterkit on this server');\n }\n await data.player.pm('You are about to receive your starter kit...');\n const itemRecords = (await takaro.item.itemControllerSearch({ filters: { id: items.map((_) => _.item) } })).data.data;\n const fullItems = items.map((item) => {\n const itemRecord = itemRecords.find((record) => record.id === item.item);\n if (!itemRecord) {\n throw new TakaroUserError(`Item with ID ${item.item} not found.`);\n }\n return {\n id: itemRecord.id,\n quality: item.quality,\n amount: item.amount,\n };\n });\n await Promise.all(fullItems.map(async (item) => {\n return takaro.gameserver.gameServerControllerGiveItem(data.gameServerId, data.player.id, {\n name: item.id,\n quality: item.quality ?? '',\n amount: item.amount,\n });\n }));\n await takaro.variable.variableControllerCreate({\n key: VARIABLE_KEY,\n value: '1',\n gameServerId: data.gameServerId,\n playerId: data.player.id,\n });\n await data.player.pm(`Gave ${items.length} items, enjoy!`);\n}\nawait main();\n//# sourceMappingURL=starterkit.js.map",
266
+ "trigger": "starterkit",
267
+ "helpText": "Get a starter kit, you can only execute this once on a server!",
268
+ "arguments": []
269
+ }
270
+ ]
271
+ }
272
+ ]
273
+ },
274
+ {
275
+ "name": "serverMessages",
276
+ "author": "Takaro",
277
+ "supportedGames": [
278
+ "all"
279
+ ],
280
+ "versions": [
281
+ {
282
+ "tag": "0.0.1",
283
+ "description": "Send automated, rotated, configurable messages to players on the server.",
284
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"messages\":{\"type\":\"array\",\"title\":\"Messages\",\"description\":\"List of messages that will be sent to players on the server.\",\"default\":[\"This is an automated message, don't forget to read the server rules!\"],\"items\":{\"type\":\"string\",\"minLength\":5,\"maxLength\":1024},\"minItems\":1}},\"required\":[\"messages\"]}",
285
+ "cronJobs": [
286
+ {
287
+ "name": "Automated message",
288
+ "temporalValue": "*/30 * * * *",
289
+ "function": "import { data, takaro } from '@takaro/helpers';\nasync function main() {\n const { module: mod, gameServerId } = data;\n // Check what the last message we sent was\n const lastMessageVar = (await takaro.variable.variableControllerSearch({\n filters: {\n key: ['lastMessage'],\n moduleId: [mod.moduleId],\n gameServerId: [gameServerId],\n },\n })).data.data[0];\n // If we haven't sent any messages yet, start with the first one\n const lastMessage = lastMessageVar ? parseInt(lastMessageVar.value, 10) : -1;\n // The next message we should send is the next in the array\n // However, if we're at the end of the array, we should start over\n const nextMessage = data.module.userConfig.messages[lastMessage + 1] ? lastMessage + 1 : 0;\n // The actual text of the message we're going to send\n const messageToSend = data.module.userConfig.messages[nextMessage];\n // Send the message to the game server\n await takaro.gameserver.gameServerControllerSendMessage(data.gameServerId, {\n message: messageToSend,\n });\n // Update the last message variable so the next time this cron job runs, we know what to send\n if (lastMessageVar) {\n // The variable already exists, update it\n await takaro.variable.variableControllerUpdate(lastMessageVar.id, {\n value: nextMessage.toString(),\n });\n }\n else {\n // The variable doesn't exist, create it\n await takaro.variable.variableControllerCreate({\n key: 'lastMessage',\n value: nextMessage.toString(),\n moduleId: mod.moduleId,\n gameServerId: gameServerId,\n });\n }\n}\nawait main();\n//# sourceMappingURL=Automated%20message.js.map"
290
+ }
291
+ ]
292
+ }
293
+ ]
294
+ },
295
+ {
296
+ "name": "chatBridge",
297
+ "author": "Takaro",
298
+ "supportedGames": [
299
+ "all"
300
+ ],
301
+ "versions": [
302
+ {
303
+ "tag": "0.0.1",
304
+ "description": "Connect chat to other services like Discord.",
305
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"sendPlayerConnected\":{\"title\":\"Send player connected\",\"type\":\"boolean\",\"description\":\"Send a message when a player connects.\",\"default\":true},\"sendPlayerDisconnected\":{\"title\":\"Send player disconnected\",\"type\":\"boolean\",\"description\":\"Send a message when a player disconnects.\",\"default\":true},\"onlyGlobalChat\":{\"title\":\"Only global chat\",\"type\":\"boolean\",\"default\":true,\"description\":\"Only relay messages from global chat. (no team chat or private messages)\"}},\"additionalProperties\":false}",
306
+ "hooks": [
307
+ {
308
+ "eventType": "discord-message",
309
+ "name": "DiscordToGame",
310
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n try {\n if (data.eventData.author.isBot)\n return;\n await takaro.gameserver.gameServerControllerSendMessage(data.gameServerId, {\n message: `[D] ${data.eventData.author.displayName}: ${data.eventData.msg}`,\n });\n }\n catch (error) {\n console.error(error);\n await takaro.discordControllerSendMessage(data.discordChannelId, {\n message: 'Failed to forward your message to the game. Please try again later.',\n });\n }\n}\nawait main();\n//# sourceMappingURL=DiscordToGame.js.map"
311
+ },
312
+ {
313
+ "eventType": "chat-message",
314
+ "name": "GameToDiscord",
315
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const onlyGlobal = data.module.userConfig.onlyGlobalChat;\n if (onlyGlobal && data.eventData.channel !== 'global')\n return;\n const discordChannel = data.module.systemConfig.hooks['DiscordToGame'].discordChannelId;\n const sender = data.player ? data.player.name : 'Non-player';\n const message = `**${sender}**: ${data.eventData.msg}`;\n await takaro.discord.discordControllerSendMessage(discordChannel, {\n message: message,\n });\n}\nawait main();\n//# sourceMappingURL=GameToDiscord.js.map"
316
+ },
317
+ {
318
+ "eventType": "player-connected",
319
+ "name": "PlayerConnected",
320
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const discordChannel = data.module.systemConfig.hooks['DiscordToGame'].discordChannelId;\n await takaro.discord.discordControllerSendMessage(discordChannel, {\n message: `[âš¡ Connected]: ${data.player.name}`,\n });\n}\nawait main();\n//# sourceMappingURL=PlayerConnected.js.map"
321
+ },
322
+ {
323
+ "eventType": "player-disconnected",
324
+ "name": "PlayerDisconnected",
325
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const discordChannel = data.module.systemConfig.hooks['DiscordToGame'].discordChannelId;\n await takaro.discord.discordControllerSendMessage(discordChannel, {\n message: `[👋 Disconnected]: ${data.player.name}`,\n });\n}\nawait main();\n//# sourceMappingURL=PlayerDisconnected.js.map"
326
+ }
327
+ ]
328
+ }
329
+ ]
330
+ },
331
+ {
332
+ "name": "gimme",
333
+ "author": "Takaro",
334
+ "supportedGames": [
335
+ "7 days to die",
336
+ "rust",
337
+ "minecraft"
338
+ ],
339
+ "versions": [
340
+ {
341
+ "tag": "0.0.3",
342
+ "description": "Randomly selects item from a list of items and entities. Fixed issue with item identifiers.",
343
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"items\":{\"x-component\":\"item\",\"type\":\"array\",\"title\":\"Items\",\"description\":\"List of items that a player can receive.\",\"uniqueItems\":true,\"items\":{\"type\":\"object\",\"title\":\"Item\",\"properties\":{\"item\":{\"type\":\"string\",\"title\":\"Item\"},\"amount\":{\"type\":\"number\",\"title\":\"Amount\"},\"quality\":{\"type\":\"string\",\"title\":\"Quality\"}}}},\"commands\":{\"title\":\"Commands\",\"type\":\"array\",\"default\":[\"say hello from gimme\"],\"items\":{\"type\":\"string\"}}},\"required\":[\"items\"],\"additionalProperties\":false}",
344
+ "uiSchema": "{\"items\":{\"items\":{\"item\":{\"ui:widget\":\"item\"}}}}",
345
+ "commands": [
346
+ {
347
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nasync function main() {\n const items = data.module.userConfig.items;\n const commands = data.module.userConfig.commands;\n if (items.length + commands.length === 0) {\n throw new TakaroUserError('No items or commands configured, please ask your server administrator to configure this module.');\n }\n // pick a random item between 0 and the length of both the items and commands arrays\n const randomIndex = Math.floor(Math.random() * (items.length + commands.length));\n const randomOption = items.concat(commands)[randomIndex];\n if (randomIndex < items.length) {\n const item = (await takaro.item.itemControllerFindOne(randomOption.item)).data.data;\n await takaro.gameserver.gameServerControllerGiveItem(data.gameServerId, data.player.id, {\n name: randomOption.item,\n amount: randomOption.amount,\n quality: randomOption.quality ?? '',\n });\n await data.player.pm(`You received ${randomOption.amount}x ${item.name}!`);\n }\n else {\n await takaro.gameserver.gameServerControllerExecuteCommand(data.gameServerId, { command: randomOption });\n }\n}\nawait main();\n//# sourceMappingURL=gimme.js.map",
348
+ "name": "gimme",
349
+ "trigger": "gimme",
350
+ "helpText": "Randomly selects item from a list of items and entities.",
351
+ "arguments": []
352
+ }
353
+ ]
354
+ }
355
+ ]
356
+ },
357
+ {
358
+ "name": "highPingKicker",
359
+ "author": "Takaro",
360
+ "supportedGames": [
361
+ "7 days to die",
362
+ "rust",
363
+ "minecraft"
364
+ ],
365
+ "versions": [
366
+ {
367
+ "tag": "0.0.2",
368
+ "description": "Automatically kick players with high ping, with warnings and configurable thresholds.",
369
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"pingThreshold\":{\"type\":\"number\",\"title\":\"Ping threshold\",\"description\":\"A ping value that is deemed too high and prompts a warning.\",\"default\":200,\"minimum\":0},\"warningsBeforeKick\":{\"type\":\"number\",\"title\":\"Kick warnings\",\"description\":\"Number of warnings before a player is kicked.\",\"default\":3,\"minimum\":0}},\"required\":[]}",
370
+ "cronJobs": [
371
+ {
372
+ "name": "Ping check",
373
+ "temporalValue": "*/5 * * * *",
374
+ "function": "import { takaro, data } from '@takaro/helpers';\nconst VARIABLE_KEY = 'highPingKicker:warnings';\nasync function main() {\n const currentPlayers = await takaro.gameserver.gameServerControllerGetPlayers(data.gameServerId);\n await Promise.all(currentPlayers.data.data.map(async (player) => {\n if (player.ping > data.module.userConfig.pingThreshold) {\n const takaroPlayerRes = await takaro.player.playerControllerSearch({\n filters: {\n steamId: [player.steamId],\n },\n });\n const takaroPlayer = takaroPlayerRes.data.data[0];\n const currentWarningsRes = await takaro.variable.variableControllerSearch({\n filters: {\n playerId: [takaroPlayer.id],\n key: [VARIABLE_KEY],\n },\n });\n const currentWarningsRecords = currentWarningsRes.data.data;\n let currentWarnings = 1;\n if (!currentWarningsRecords.length) {\n await takaro.variable.variableControllerCreate({\n playerId: takaroPlayer.id,\n key: VARIABLE_KEY,\n value: '1',\n });\n }\n else {\n currentWarnings = parseInt(currentWarningsRecords[0].value, 10) + 1;\n await takaro.variable.variableControllerUpdate(currentWarningsRecords[0].id, {\n value: currentWarnings.toString(),\n });\n }\n // Check if player should be kicked before sending warning\n if (currentWarnings >= data.module.userConfig.warningsBeforeKick) {\n await takaro.gameserver.gameServerControllerKickPlayer(data.gameServerId, takaroPlayer.id, {\n reason: `Your ping (${player.ping}) is too high, please try again later.`,\n });\n // Delete the warning record after kicking\n if (currentWarningsRecords.length > 0) {\n await takaro.variable.variableControllerDelete(currentWarningsRecords[0].id);\n }\n }\n else {\n // Only send warning if player won't be kicked\n await takaro.gameserver.gameServerControllerSendMessage(data.gameServerId, {\n message: `Your ping (${player.ping}) is too high. Warning ${currentWarnings}/${data.module.userConfig.warningsBeforeKick}`,\n opts: {\n recipient: {\n gameId: player.gameId,\n },\n },\n });\n }\n }\n }));\n}\nawait main();\n//# sourceMappingURL=Ping%20check.js.map"
375
+ }
376
+ ]
377
+ }
378
+ ]
379
+ },
380
+ {
381
+ "name": "economyUtils",
382
+ "author": "Takaro",
383
+ "supportedGames": [
384
+ "all"
385
+ ],
386
+ "versions": [
387
+ {
388
+ "tag": "0.0.3",
389
+ "description": "A set of commands to allow players to manage their currency.",
390
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"pendingAmount\":{\"title\":\"Pending amount\",\"type\":\"number\",\"description\":\"When a player transfers money, they must confirm the transfer when the amount is equal or above this value. Set to 0 to disable.\",\"default\":0},\"zombieKillReward\":{\"title\":\"Zombie kill reward\",\"type\":\"number\",\"description\":\"The default amount of currency a player receives for killing a zombie. This can be overridden by roles.\",\"default\":1}},\"required\":[],\"additionalProperties\":false}",
391
+ "permissions": [
392
+ {
393
+ "permission": "ECONOMY_UTILS_MANAGE_CURRENCY",
394
+ "friendlyName": "Manage currency",
395
+ "description": "Allows players to manage currency of other players. This includes granting and revoking currency.",
396
+ "canHaveCount": false
397
+ },
398
+ {
399
+ "permission": "ZOMBIE_KILL_REWARD_OVERRIDE",
400
+ "friendlyName": "Zombie kill reward override",
401
+ "description": "Allows a role to override the amount of currency a player receives for killing a entity.",
402
+ "canHaveCount": true
403
+ }
404
+ ],
405
+ "cronJobs": [
406
+ {
407
+ "function": "import { data, takaro, checkPermission } from '@takaro/helpers';\nconst VARIABLE_KEY = 'lastZombieKillReward';\nasync function main() {\n const { gameServerId, module: mod } = data;\n const lastRunRes = (await takaro.variable.variableControllerSearch({\n filters: {\n key: [VARIABLE_KEY],\n gameServerId: [gameServerId],\n moduleId: [mod.moduleId],\n },\n })).data.data;\n // We last ran the rewards script at this time\n // If this is the first time we run it, just get the last 5 minutes\n const lastRun = lastRunRes.length ? new Date(JSON.parse(lastRunRes[0].value)) : new Date(Date.now() - 5 * 60 * 1000);\n // Fetch all the kill events since the last time we gave out rewards\n const killEvents = (await takaro.event.eventControllerSearch({\n filters: { eventName: ['entity-killed'], gameserverId: [gameServerId] },\n greaterThan: { createdAt: lastRun.toISOString() },\n limit: 1000,\n })).data.data;\n console.log(`Found ${killEvents.length} kill events since ${lastRun.toISOString()}`);\n // Group the events by player\n const playerKills = {};\n for (const killEvent of killEvents) {\n if (!playerKills[killEvent.playerId]) {\n playerKills[killEvent.playerId] = [];\n }\n playerKills[killEvent.playerId].push(killEvent);\n }\n // Give each player their reward\n // We use Promise.allSettled to run this concurrently\n const results = await Promise.allSettled(Object.entries(playerKills).map(async ([playerId, kills]) => {\n const pog = (await takaro.playerOnGameserver.playerOnGameServerControllerGetOne(gameServerId, playerId)).data\n .data;\n const hasPermission = checkPermission(pog, 'ZOMBIE_KILL_REWARD_OVERRIDE');\n const defaultReward = mod.userConfig.zombieKillReward;\n const reward = hasPermission && hasPermission.count != null ? hasPermission.count : defaultReward;\n const totalReward = reward * kills.length;\n return takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(gameServerId, playerId, {\n currency: totalReward,\n });\n }));\n // Log any errors\n for (const result of results) {\n if (result.status === 'rejected') {\n console.error(result.reason);\n throw new Error(`Failed to give rewards: ${result.reason}`);\n }\n }\n // Update the last run time\n if (lastRunRes.length) {\n await takaro.variable.variableControllerUpdate(lastRunRes[0].id, {\n value: JSON.stringify(new Date()),\n });\n }\n else {\n await takaro.variable.variableControllerCreate({\n key: VARIABLE_KEY,\n value: JSON.stringify(new Date()),\n moduleId: mod.moduleId,\n gameServerId,\n });\n }\n}\nawait main();\n//# sourceMappingURL=zombieKillReward.js.map",
408
+ "name": "zombieKillReward",
409
+ "temporalValue": "*/5 * * * *"
410
+ }
411
+ ],
412
+ "commands": [
413
+ {
414
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', data.gameServerId)).data.data;\n await data.player.pm(`balance: ${data.pog.currency} ${currencyName.value}`);\n}\nawait main();\n//# sourceMappingURL=balance.js.map",
415
+ "name": "balance",
416
+ "trigger": "balance",
417
+ "helpText": "Check your balance.",
418
+ "arguments": []
419
+ },
420
+ {
421
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const richest = (await takaro.playerOnGameserver.playerOnGameServerControllerSearch({\n limit: 10,\n sortBy: 'currency',\n sortDirection: 'desc',\n extend: ['player'],\n })).data.data;\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', data.gameServerId)).data.data\n .value;\n // TODO: change this to name when it become available in playerOnGameServer\n const richestStrings = richest.map(async (pog, index) => {\n const playerName = (await takaro.player.playerControllerGetOne(pog.playerId)).data.data.name;\n return `${index + 1}. ${playerName} - ${pog.currency} ${currencyName}`;\n });\n await data.player.pm('Richest players:');\n for (const string of richestStrings) {\n await data.player.pm(await string);\n }\n}\nawait main();\n//# sourceMappingURL=topCurrency.js.map",
422
+ "name": "topCurrency",
423
+ "trigger": "topcurrency",
424
+ "helpText": "List of the 10 players with the highest balance.",
425
+ "arguments": []
426
+ },
427
+ {
428
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const { pog: granter, arguments: args, gameServerId } = data;\n // args.receiver has an argument type of \"player\". Arguments of this type are automatically resolved to the player's id.\n // If the player doesn't exist or multiple players with the same name where found, it will have thrown an error before this command is executed.\n const receiver = args.receiver;\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', gameServerId)).data.data.value;\n const granterName = (await takaro.player.playerControllerGetOne(granter.playerId)).data.data.name;\n const receiverName = (await takaro.player.playerControllerGetOne(receiver.playerId)).data.data.name;\n await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(receiver.gameServerId, receiver.playerId, {\n currency: args.amount,\n });\n const messageToReceiver = takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n message: `Granted ${args.amount} ${currencyName} by ${granterName}`,\n opts: {\n recipient: {\n gameId: receiver.gameId,\n },\n },\n });\n await Promise.all([\n granter.pm(`You successfully granted ${args.amount} ${currencyName} to ${receiverName}`),\n messageToReceiver,\n ]);\n return;\n}\nawait main();\n//# sourceMappingURL=grantCurrency.js.map",
429
+ "name": "grantCurrency",
430
+ "trigger": "grantcurrency",
431
+ "helpText": "Grant money to a player. The money is not taken from your own balance but is new currency.",
432
+ "requiredPermissions": [
433
+ "ECONOMY_UTILS_MANAGE_CURRENCY"
434
+ ],
435
+ "arguments": [
436
+ {
437
+ "name": "receiver",
438
+ "type": "player",
439
+ "helpText": "The player to grant currency to.",
440
+ "position": 0,
441
+ "defaultValue": null
442
+ },
443
+ {
444
+ "name": "amount",
445
+ "type": "number",
446
+ "helpText": "The amount of money.",
447
+ "position": 1,
448
+ "defaultValue": null
449
+ }
450
+ ]
451
+ },
452
+ {
453
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const { pog: revoker, arguments: args, gameServerId } = data;\n // args.receiver has an argument type of \"player\". Arguments of this type are automatically resolved to the player's id.\n // If the player doesn't exist or multiple players with the same name where found, it will have thrown an error before this command is executed.\n const receiver = args.receiver;\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', gameServerId)).data.data.value;\n const revokerName = (await takaro.player.playerControllerGetOne(revoker.playerId)).data.data.name;\n const receiverName = (await takaro.player.playerControllerGetOne(receiver.playerId)).data.data.name;\n await takaro.playerOnGameserver.playerOnGameServerControllerDeductCurrency(receiver.gameServerId, receiver.playerId, {\n currency: args.amount,\n });\n const messageToReceiver = takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n message: `${args.amount} ${currencyName} were revoked by ${revokerName}`,\n opts: {\n recipient: {\n gameId: receiver.gameId,\n },\n },\n });\n await Promise.all([\n revoker.pm(`You successfully revoked ${args.amount} ${currencyName} of ${receiverName}'s balance`),\n messageToReceiver,\n ]);\n return;\n}\nawait main();\n//# sourceMappingURL=revokeCurrency.js.map",
454
+ "name": "revokeCurrency",
455
+ "trigger": "revokecurrency",
456
+ "helpText": "Revokes money from a player. The money disappears.",
457
+ "requiredPermissions": [
458
+ "ECONOMY_UTILS_MANAGE_CURRENCY"
459
+ ],
460
+ "arguments": [
461
+ {
462
+ "name": "receiver",
463
+ "type": "player",
464
+ "helpText": "The player to revoke currency from.",
465
+ "position": 0,
466
+ "defaultValue": null
467
+ },
468
+ {
469
+ "name": "amount",
470
+ "type": "number",
471
+ "helpText": "The amount of money.",
472
+ "position": 1,
473
+ "defaultValue": null
474
+ }
475
+ ]
476
+ },
477
+ {
478
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nasync function main() {\n const { gameServerId, pog: sender, module: mod } = data;\n // try to find a variable with key \"confirmTransfer\"\n const variables = (await takaro.variable.variableControllerSearch({\n filters: {\n key: ['confirmTransfer'],\n gameServerId: [gameServerId],\n moduleId: [mod.moduleId],\n playerId: [sender.playerId],\n },\n })).data.data;\n if (variables.length === 0) {\n throw new TakaroUserError('You have no pending transfer.');\n }\n // Remove the variable before potentially executing the transaction.\n await takaro.variable.variableControllerDelete(variables[0].id);\n const pendingTransfer = JSON.parse(variables[0].value);\n await takaro.playerOnGameserver.playerOnGameServerControllerTransactBetweenPlayers(sender.gameServerId, sender.id, pendingTransfer.receiver.id, {\n currency: pendingTransfer.amount,\n });\n const receiverName = (await takaro.player.playerControllerGetOne(pendingTransfer.receiver.playerId)).data.data.name;\n const senderName = (await takaro.player.playerControllerGetOne(sender.playerId)).data.data.name;\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', gameServerId)).data.data.value;\n const messageToSender = sender.pm(`You successfully transferred ${pendingTransfer.amount} ${currencyName} to ${receiverName}`);\n const messageToReceiver = takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n message: `You received ${pendingTransfer.amount} ${currencyName} from ${senderName}`,\n opts: {\n recipient: {\n gameId: pendingTransfer.receiver.gameId,\n },\n },\n });\n await Promise.all([messageToSender, messageToReceiver]);\n return;\n}\nawait main();\n//# sourceMappingURL=confirmTransfer.js.map",
479
+ "name": "confirmTransfer",
480
+ "trigger": "confirmtransfer",
481
+ "helpText": "Confirms a pending transfer.",
482
+ "arguments": []
483
+ },
484
+ {
485
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nasync function main() {\n const { pog: sender, arguments: args, gameServerId, module: mod } = data;\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', gameServerId)).data.data.value;\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n // args.receiver has an argument type of \"player\". Arguments of this type are automatically resolved to the player's id.\n // If the player doesn't exist or multiple players with the same name where found, it will have thrown an error before this command is executed.\n const receiver = args.receiver;\n const senderName = (await takaro.player.playerControllerGetOne(sender.playerId)).data.data.name;\n const receiverName = (await takaro.player.playerControllerGetOne(receiver.playerId)).data.data.name;\n if (mod.userConfig.pendingAmount !== 0 && args.amount >= mod.userConfig.pendingAmount) {\n // create a variable to store confirmation requirement\n // TODO: in the future, we should probably add an expiration date to this variable.\n await takaro.variable.variableControllerCreate({\n key: 'confirmTransfer',\n value: JSON.stringify({\n amount: args.amount,\n receiver: {\n id: receiver.id,\n gameId: receiver.gameId,\n playerId: receiver.playerId,\n },\n }),\n moduleId: mod.moduleId,\n playerId: sender.playerId,\n gameServerId,\n });\n // NOTE: we should maybe check if the player has enough balance to send the amount since this is only checked when the transaction is executed.\n await sender.pm(`You are about to send ${args.amount} ${currencyName} to ${receiverName}. (Please confirm by typing ${prefix}confirmtransfer)`);\n return;\n }\n try {\n await takaro.playerOnGameserver.playerOnGameServerControllerTransactBetweenPlayers(sender.gameServerId, sender.id, receiver.id, {\n currency: args.amount,\n });\n }\n catch {\n throw new TakaroUserError(`Failed to transfer ${args.amount} ${currencyName} to ${receiverName}. Are you sure you have enough balance?`);\n }\n const messageToReceiver = takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n message: `You received ${args.amount} ${currencyName} from ${senderName}`,\n opts: {\n recipient: {\n gameId: receiver.gameId,\n },\n },\n });\n await Promise.all([\n sender.pm(`You successfully transferred ${args.amount} ${currencyName} to ${receiverName}`),\n messageToReceiver,\n ]);\n return;\n}\nawait main();\n//# sourceMappingURL=transfer.js.map",
486
+ "name": "transfer",
487
+ "trigger": "transfer",
488
+ "helpText": "Transfer money to another player.",
489
+ "arguments": [
490
+ {
491
+ "name": "receiver",
492
+ "type": "player",
493
+ "helpText": "The player to transfer money to.",
494
+ "position": 0,
495
+ "defaultValue": null
496
+ },
497
+ {
498
+ "name": "amount",
499
+ "type": "number",
500
+ "helpText": "The amount of money to transfer.",
501
+ "position": 1,
502
+ "defaultValue": null
503
+ }
504
+ ]
505
+ },
506
+ {
507
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nasync function main() {\n const { user, player, arguments: args, gameServerId } = data;\n if (!user)\n throw new TakaroUserError('You must link your account to Takaro to use this command.');\n const filters = {\n userId: [user.id],\n status: ['PAID'],\n };\n // Only filter by gameServerId if it's available (should always be present in command context)\n if (gameServerId) {\n filters.gameServerId = [gameServerId];\n }\n const pendingOrdersRes = await takaro.shopOrder.shopOrderControllerSearch({\n filters,\n sortBy: 'createdAt',\n sortDirection: 'asc',\n });\n if (pendingOrdersRes.data.data.length === 0) {\n await player.pm('You have no pending orders.');\n return;\n }\n let ordersToClaim = [];\n if (args.all) {\n ordersToClaim = pendingOrdersRes.data.data;\n }\n else {\n ordersToClaim.push(pendingOrdersRes.data.data[0]);\n }\n for (const order of ordersToClaim) {\n await takaro.shopOrder.shopOrderControllerClaim(order.id);\n }\n}\nawait main();\n//# sourceMappingURL=claim.js.map",
508
+ "name": "claim",
509
+ "trigger": "claim",
510
+ "helpText": "Claim your pending shop orders.",
511
+ "arguments": [
512
+ {
513
+ "name": "all",
514
+ "type": "boolean",
515
+ "helpText": "If true, claim ALL pending orders. If false, claim only the first one.",
516
+ "position": 0,
517
+ "defaultValue": "false"
518
+ }
519
+ ]
520
+ },
521
+ {
522
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nasync function main() {\n const { arguments: args, player, gameServerId } = data;\n const { page, item, action } = args;\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n // If command is called without any arguments\n const messageWithoutPrefix = data.chatMessage.msg.slice(prefix.length).trim();\n if (!messageWithoutPrefix.includes(' ')) {\n await player.pm('This command allows you to browse the shop and view available items.');\n await player.pm(`Usage: ${prefix}shop [page] [item] [action]`);\n await player.pm(`${prefix}shop 2 - View the second page of shop items`);\n await player.pm(`${prefix}shop 1 3 - View details about the third item on the first page`);\n await player.pm(`${prefix}shop 1 3 buy - Purchase the third item on the first page`);\n return;\n }\n const shopItems = await takaro.shopListing.shopListingControllerSearch({\n limit: 5,\n page: page - 1,\n sortBy: 'name',\n sortDirection: 'asc',\n filters: {\n gameServerId: [gameServerId],\n draft: false,\n },\n });\n if (shopItems.data.data.length === 0) {\n await player.pm('No items found.');\n return;\n }\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', data.gameServerId)).data.data;\n if (!item) {\n // List the shop items with index\n let index = 1;\n for (const listing of shopItems.data.data) {\n const items = listing.items.slice(0, 3).map((item) => {\n return `${item.amount}x ${item.item.name}`;\n });\n await player.pm(`${index} - ${listing.name} - ${listing.price} ${currencyName.value}. ${items.join(', ')}`);\n index++;\n }\n return;\n }\n const selectedItem = shopItems.data.data[item - 1];\n if (!selectedItem)\n throw new TakaroUserError(`Item not found. Please select an item from the list, valid options are 1-${shopItems.data.data.length}.`);\n if (action === 'none') {\n // Display more info about the item\n await player.pm(`Listing ${selectedItem.name} - ${selectedItem.price} ${currencyName.value}`);\n await Promise.all(selectedItem.items.map((item) => {\n const quality = item.quality ? `Quality: ${item.quality}` : '';\n const description = (item.item.description ? `Description: ${item.item.description}` : '').replaceAll('\\\\n', ' ');\n return player.pm(`- ${item.amount}x ${item.item.name}. ${quality} ${description}`);\n }));\n return;\n }\n if (action === 'buy') {\n const orderRes = await takaro.shopOrder.shopOrderControllerCreate({\n amount: 1,\n listingId: selectedItem.id,\n playerId: player.id,\n });\n await player.pm(`You have purchased ${selectedItem.name} for ${selectedItem.price} ${currencyName.value}.`);\n await takaro.shopOrder.shopOrderControllerClaim(orderRes.data.data.id);\n return;\n }\n throw new TakaroUserError('Invalid action. Valid actions are \"buy\".');\n}\nawait main();\n//# sourceMappingURL=shop.js.map",
523
+ "name": "shop",
524
+ "trigger": "shop",
525
+ "helpText": "Browse the shop and view available items.",
526
+ "arguments": [
527
+ {
528
+ "name": "page",
529
+ "type": "number",
530
+ "helpText": "Display more items from the shop by specifying a page number.",
531
+ "position": 0,
532
+ "defaultValue": "1"
533
+ },
534
+ {
535
+ "name": "item",
536
+ "type": "number",
537
+ "helpText": "Select a specific item to view more details.",
538
+ "position": 1,
539
+ "defaultValue": "0"
540
+ },
541
+ {
542
+ "name": "action",
543
+ "type": "string",
544
+ "helpText": "Perform an action on the selected item. Currently only \"buy\" is supported.",
545
+ "position": 2,
546
+ "defaultValue": "none"
547
+ }
548
+ ]
549
+ }
550
+ ]
551
+ }
552
+ ]
553
+ },
554
+ {
555
+ "name": "lottery",
556
+ "author": "Takaro",
557
+ "supportedGames": [
558
+ "all"
559
+ ],
560
+ "versions": [
561
+ {
562
+ "tag": "0.0.2",
563
+ "description": "Players can buy tickets for a lottery, and the winner is chosen at random.",
564
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"profitMargin\":{\"type\":\"number\",\"maximum\":1,\"minimum\":0,\"description\":\"The profit margin the server takes from the lottery.\",\"default\":0.1}},\"required\":[],\"additionalProperties\":false}",
565
+ "permissions": [
566
+ {
567
+ "permission": "LOTTERY_BUY",
568
+ "friendlyName": "Buy Lottery Tickets",
569
+ "canHaveCount": false,
570
+ "description": "Allows the player to buy lottery tickets."
571
+ },
572
+ {
573
+ "permission": "LOTTERY_VIEW_TICKETS",
574
+ "friendlyName": "View Lottery Tickets",
575
+ "description": "Allows the player to view his lottery tickets.",
576
+ "canHaveCount": false
577
+ }
578
+ ],
579
+ "cronJobs": [
580
+ {
581
+ "name": "drawLottery",
582
+ "temporalValue": "0 0 * * *",
583
+ "function": "import { takaro, data } from '@takaro/helpers';\nfunction getTotalPrize(tickets, ticketPrice, profitMargin) {\n const amount = tickets.reduce((acc, ticket) => {\n const ticketAmount = parseInt(JSON.parse(ticket.value).amount, 10);\n return acc + ticketAmount;\n }, 0);\n const rawTotal = amount * ticketPrice;\n const profit = rawTotal * profitMargin;\n const totalPrize = rawTotal - profit;\n return totalPrize;\n}\nasync function drawWinner(takaro, gameServerId, tickets) {\n const randomIndex = Math.floor(Math.random() * tickets.length);\n const winnerTicket = tickets[randomIndex];\n const winner = (await takaro.player.playerControllerGetOne(winnerTicket.playerId)).data.data;\n const pog = await takaro.playerOnGameserver.playerOnGameServerControllerSearch({\n filters: {\n gameServerId: [gameServerId],\n playerId: [winner.id],\n },\n });\n return {\n name: winner.name,\n playerId: pog.data.data[0].playerId,\n };\n}\nasync function refundPlayer(takaro, gameServerId, playerId, amount, currencyName) {\n const pog = (await takaro.playerOnGameserver.playerOnGameServerControllerSearch({\n filters: {\n gameServerId: [gameServerId],\n playerId: [playerId],\n },\n })).data.data[0];\n await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(gameServerId, pog.playerId, {\n currency: amount,\n });\n await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n message: `You have been refunded ${amount} ${currencyName} because the lottery has been cancelled.`,\n opts: {\n recipient: {\n gameId: pog.gameId,\n },\n },\n });\n}\nasync function cleanUp(takaro, tickets) {\n const deleteTasks = tickets.map((ticket) => takaro.variable.variableControllerDelete(ticket.id));\n await Promise.allSettled(deleteTasks);\n}\nasync function main() {\n const { gameServerId, module: mod } = data;\n let tickets = [];\n try {\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', gameServerId)).data.data.value;\n const ticketCost = mod.systemConfig.commands.buyTicket.cost;\n tickets = (await takaro.variable.variableControllerSearch({\n filters: {\n gameServerId: [gameServerId],\n moduleId: [mod.moduleId],\n key: ['lottery_tickets_bought'],\n },\n })).data.data;\n if (tickets.length === 0) {\n await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n message: 'No one has bought any tickets. The lottery has been cancelled.',\n });\n return;\n }\n if (tickets.length === 1) {\n await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n message: 'Only one person has bought a ticket. The lottery has been cancelled.',\n });\n const amount = parseInt(JSON.parse(tickets[0].value).amount, 10) * ticketCost;\n await refundPlayer(takaro, gameServerId, tickets[0].playerId, amount, currencyName);\n return;\n }\n const totalPrize = getTotalPrize(tickets, ticketCost, mod.userConfig.profitMargin);\n const { name: winnerName, playerId } = await drawWinner(takaro, gameServerId, tickets);\n await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n message: 'The lottery raffle is about to start!',\n });\n await takaro.gameserver.gameServerControllerSendMessage(gameServerId, { message: 'drumrolls please...' });\n await takaro.gameserver.gameServerControllerSendMessage(gameServerId, { message: 'The winner is...' });\n await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(gameServerId, playerId, {\n currency: totalPrize,\n });\n await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n message: `${winnerName}! Congratulations! You have won ${totalPrize} ${currencyName}!`,\n });\n }\n finally {\n await cleanUp(takaro, tickets);\n }\n}\nawait main();\n//# sourceMappingURL=drawLottery.js.map"
584
+ }
585
+ ],
586
+ "commands": [
587
+ {
588
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nasync function main() {\n const { pog, gameServerId, arguments: args, module: mod } = data;\n const varKey = 'lottery_tickets_bought';\n if (args.amount < 1) {\n throw new TakaroUserError('You must buy at least 1 ticket.');\n }\n const tickets = (await takaro.variable.variableControllerSearch({\n filters: {\n gameServerId: [gameServerId],\n key: [varKey],\n moduleId: [mod.moduleId],\n playerId: [pog.playerId],\n },\n })).data.data;\n // Player already has some tickets bought\n if (tickets.length > 0) {\n const ticketsBought = tickets[0];\n const ticketsBoughtAmount = parseInt(JSON.parse(ticketsBought.value).amount, 10);\n await takaro.variable.variableControllerUpdate(ticketsBought.id, {\n key: varKey,\n playerId: pog.playerId,\n moduleId: mod.moduleId,\n gameServerId,\n value: JSON.stringify({ amount: ticketsBoughtAmount + args.amount }),\n });\n }\n // Player has no tickets bought\n else {\n await takaro.variable.variableControllerCreate({\n key: varKey,\n value: JSON.stringify({\n amount: args.amount,\n }),\n gameServerId,\n moduleId: mod.moduleId,\n playerId: pog.playerId,\n });\n }\n const ticketPrice = args.amount * mod.systemConfig.commands.buyTicket.cost;\n // The price of the first ticket is deducted by the command execution itself.\n if (args.amount > 1) {\n await takaro.playerOnGameserver.playerOnGameServerControllerDeductCurrency(gameServerId, pog.playerId, {\n currency: ticketPrice - 1,\n });\n }\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', gameServerId)).data.data.value;\n await pog.pm(`You have successfully bought ${args.amount} tickets for ${ticketPrice} ${currencyName}. Good luck!`);\n}\nawait main();\n//# sourceMappingURL=buyTicket.js.map",
589
+ "name": "buyTicket",
590
+ "trigger": "buyTicket",
591
+ "helpText": "Buy a lottery ticket.",
592
+ "requiredPermissions": [
593
+ "LOTTERY_BUY"
594
+ ],
595
+ "arguments": [
596
+ {
597
+ "name": "amount",
598
+ "type": "number",
599
+ "helpText": "The amount of tickets to buy.",
600
+ "position": 0,
601
+ "defaultValue": null
602
+ }
603
+ ]
604
+ },
605
+ {
606
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const varKey = 'lottery_tickets_bought';\n const tickets = (await takaro.variable.variableControllerSearch({\n filters: {\n gameServerId: [gameServerId],\n key: [varKey],\n moduleId: [mod.moduleId],\n playerId: [pog.playerId],\n },\n })).data.data;\n let ticketsBought = 0;\n if (tickets.length === 1) {\n ticketsBought = parseInt(JSON.parse(tickets[0].value).amount, 10);\n }\n await pog.pm(`You have bought ${ticketsBought} tickets.`);\n}\nawait main();\n//# sourceMappingURL=viewTickets.js.map",
607
+ "name": "viewTickets",
608
+ "trigger": "viewTickets",
609
+ "helpText": "View your lottery tickets.",
610
+ "requiredPermissions": [
611
+ "LOTTERY_VIEW_TICKETS"
612
+ ],
613
+ "arguments": []
614
+ },
615
+ {
616
+ "function": "import { nextCronJobRun, data } from '@takaro/helpers';\nfunction formatTimeToReach(cronJob) {\n const targetDate = nextCronJobRun(cronJob);\n // Get the current date and time\n const currentDate = new Date();\n // Calculate the time difference in milliseconds\n const delta = targetDate - currentDate;\n // Calculate days, hours, minutes, and seconds\n const days = Math.floor(delta / (1000 * 60 * 60 * 24));\n const hours = Math.floor((delta % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));\n const minutes = Math.floor((delta % (1000 * 60 * 60)) / (1000 * 60));\n const seconds = Math.floor((delta % (1000 * 60)) / 1000);\n // Build the formatted string\n let formattedString = '';\n if (days > 0) {\n formattedString += `${days} day${days > 1 ? 's' : ''} `;\n }\n if (hours > 0) {\n formattedString += `${hours} hour${hours > 1 ? 's' : ''} `;\n }\n if (minutes > 0) {\n formattedString += `${minutes} minute${minutes > 1 ? 's' : ''} `;\n }\n if (seconds > 0) {\n formattedString += `${seconds} second${seconds > 1 ? 's' : ''} `;\n }\n return formattedString.trim();\n}\nasync function main() {\n const { player, module: mod } = data;\n await player.pm(`The next lottery draw is in about ${formatTimeToReach(mod.systemConfig.cronJobs.drawLottery.temporalValue)}`);\n}\nawait main();\n//# sourceMappingURL=nextDraw.js.map",
617
+ "name": "nextDraw",
618
+ "trigger": "nextDraw",
619
+ "helpText": "View when the next draw is.",
620
+ "arguments": []
621
+ }
622
+ ]
623
+ }
624
+ ]
625
+ },
626
+ {
627
+ "name": "geoBlock",
628
+ "author": "Takaro",
629
+ "supportedGames": [
630
+ "all"
631
+ ],
632
+ "versions": [
633
+ {
634
+ "tag": "0.0.1",
635
+ "description": "Block players from certain countries from joining the server.",
636
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"mode\":{\"title\":\"Mode\",\"type\":\"string\",\"description\":\"If set to allow, only players from the specified countries will be allowed to join. If set to deny, players from the specified countries will be banned from the server.\",\"enum\":[\"allow\",\"deny\"],\"default\":\"deny\"},\"countries\":{\"title\":\"Countries\",\"description\":\"List of countries\",\"type\":\"array\",\"uniqueItems\":true,\"x-component\":\"country\",\"items\":{\"type\":\"string\",\"anyOf\":[{\"const\":\"AF\",\"title\":\"Afghanistan\"},{\"const\":\"AX\",\"title\":\"Aland Islands\"},{\"const\":\"AL\",\"title\":\"Albania\"},{\"const\":\"DZ\",\"title\":\"Algeria\"},{\"const\":\"AS\",\"title\":\"American Samoa\"},{\"const\":\"AD\",\"title\":\"Andorra\"},{\"const\":\"AO\",\"title\":\"Angola\"},{\"const\":\"AI\",\"title\":\"Anguilla\"},{\"const\":\"AQ\",\"title\":\"Antarctica\"},{\"const\":\"AG\",\"title\":\"Antigua And Barbuda\"},{\"const\":\"AR\",\"title\":\"Argentina\"},{\"const\":\"AM\",\"title\":\"Armenia\"},{\"const\":\"AW\",\"title\":\"Aruba\"},{\"const\":\"AU\",\"title\":\"Australia\"},{\"const\":\"AT\",\"title\":\"Austria\"},{\"const\":\"AZ\",\"title\":\"Azerbaijan\"},{\"const\":\"BS\",\"title\":\"Bahamas\"},{\"const\":\"BH\",\"title\":\"Bahrain\"},{\"const\":\"BD\",\"title\":\"Bangladesh\"},{\"const\":\"BB\",\"title\":\"Barbados\"},{\"const\":\"BY\",\"title\":\"Belarus\"},{\"const\":\"BE\",\"title\":\"Belgium\"},{\"const\":\"BZ\",\"title\":\"Belize\"},{\"const\":\"BJ\",\"title\":\"Benin\"},{\"const\":\"BM\",\"title\":\"Bermuda\"},{\"const\":\"BT\",\"title\":\"Bhutan\"},{\"const\":\"BO\",\"title\":\"Bolivia\"},{\"const\":\"BA\",\"title\":\"Bosnia And Herzegovina\"},{\"const\":\"BW\",\"title\":\"Botswana\"},{\"const\":\"BV\",\"title\":\"Bouvet Island\"},{\"const\":\"BR\",\"title\":\"Brazil\"},{\"const\":\"IO\",\"title\":\"British Indian Ocean Territory\"},{\"const\":\"BN\",\"title\":\"Brunei Darussalam\"},{\"const\":\"BG\",\"title\":\"Bulgaria\"},{\"const\":\"BF\",\"title\":\"Burkina Faso\"},{\"const\":\"BI\",\"title\":\"Burundi\"},{\"const\":\"KH\",\"title\":\"Cambodia\"},{\"const\":\"CM\",\"title\":\"Cameroon\"},{\"const\":\"CA\",\"title\":\"Canada\"},{\"const\":\"CV\",\"title\":\"Cape Verde\"},{\"const\":\"KY\",\"title\":\"Cayman Islands\"},{\"const\":\"CF\",\"title\":\"Central African Republic\"},{\"const\":\"TD\",\"title\":\"Chad\"},{\"const\":\"CL\",\"title\":\"Chile\"},{\"const\":\"CN\",\"title\":\"China\"},{\"const\":\"CX\",\"title\":\"Christmas Island\"},{\"const\":\"CC\",\"title\":\"Cocos (Keeling) Islands\"},{\"const\":\"CO\",\"title\":\"Colombia\"},{\"const\":\"KM\",\"title\":\"Comoros\"},{\"const\":\"CG\",\"title\":\"Congo\"},{\"const\":\"CD\",\"title\":\"Congo, Democratic Republic\"},{\"const\":\"CK\",\"title\":\"Cook Islands\"},{\"const\":\"CR\",\"title\":\"Costa Rica\"},{\"const\":\"CI\",\"title\":\"Cote D'Ivoire\"},{\"const\":\"HR\",\"title\":\"Croatia\"},{\"const\":\"CU\",\"title\":\"Cuba\"},{\"const\":\"CY\",\"title\":\"Cyprus\"},{\"const\":\"CZ\",\"title\":\"Czech Republic\"},{\"const\":\"DK\",\"title\":\"Denmark\"},{\"const\":\"DJ\",\"title\":\"Djibouti\"},{\"const\":\"DM\",\"title\":\"Dominica\"},{\"const\":\"DO\",\"title\":\"Dominican Republic\"},{\"const\":\"EC\",\"title\":\"Ecuador\"},{\"const\":\"EG\",\"title\":\"Egypt\"},{\"const\":\"SV\",\"title\":\"El Salvador\"},{\"const\":\"GQ\",\"title\":\"Equatorial Guinea\"},{\"const\":\"ER\",\"title\":\"Eritrea\"},{\"const\":\"EE\",\"title\":\"Estonia\"},{\"const\":\"ET\",\"title\":\"Ethiopia\"},{\"const\":\"FK\",\"title\":\"Falkland Islands (Malvinas)\"},{\"const\":\"FO\",\"title\":\"Faroe Islands\"},{\"const\":\"FJ\",\"title\":\"Fiji\"},{\"const\":\"FI\",\"title\":\"Finland\"},{\"const\":\"FR\",\"title\":\"France\"},{\"const\":\"GF\",\"title\":\"French Guiana\"},{\"const\":\"PF\",\"title\":\"French Polynesia\"},{\"const\":\"TF\",\"title\":\"French Southern Territories\"},{\"const\":\"GA\",\"title\":\"Gabon\"},{\"const\":\"GM\",\"title\":\"Gambia\"},{\"const\":\"GE\",\"title\":\"Georgia\"},{\"const\":\"DE\",\"title\":\"Germany\"},{\"const\":\"GH\",\"title\":\"Ghana\"},{\"const\":\"GI\",\"title\":\"Gibraltar\"},{\"const\":\"GR\",\"title\":\"Greece\"},{\"const\":\"GL\",\"title\":\"Greenland\"},{\"const\":\"GD\",\"title\":\"Grenada\"},{\"const\":\"GP\",\"title\":\"Guadeloupe\"},{\"const\":\"GU\",\"title\":\"Guam\"},{\"const\":\"GT\",\"title\":\"Guatemala\"},{\"const\":\"GG\",\"title\":\"Guernsey\"},{\"const\":\"GN\",\"title\":\"Guinea\"},{\"const\":\"GW\",\"title\":\"Guinea-Bissau\"},{\"const\":\"GY\",\"title\":\"Guyana\"},{\"const\":\"HT\",\"title\":\"Haiti\"},{\"const\":\"VA\",\"title\":\"Holy See (Vatican City State)\"},{\"const\":\"HN\",\"title\":\"Honduras\"},{\"const\":\"HK\",\"title\":\"Hong Kong\"},{\"const\":\"HU\",\"title\":\"Hungary\"},{\"const\":\"IS\",\"title\":\"Iceland\"},{\"const\":\"IN\",\"title\":\"India\"},{\"const\":\"ID\",\"title\":\"Indonesia\"},{\"const\":\"IR\",\"title\":\"Iran, Islamic Republic Of\"},{\"const\":\"IQ\",\"title\":\"Iraq\"},{\"const\":\"IE\",\"title\":\"Ireland\"},{\"const\":\"IM\",\"title\":\"Isle Of Man\"},{\"const\":\"IL\",\"title\":\"Israel\"},{\"const\":\"IT\",\"title\":\"Italy\"},{\"const\":\"JM\",\"title\":\"Jamaica\"},{\"const\":\"JP\",\"title\":\"Japan\"},{\"const\":\"JE\",\"title\":\"Jersey\"},{\"const\":\"JO\",\"title\":\"Jordan\"},{\"const\":\"KZ\",\"title\":\"Kazakhstan\"},{\"const\":\"KE\",\"title\":\"Kenya\"},{\"const\":\"KI\",\"title\":\"Kiribati\"},{\"const\":\"KR\",\"title\":\"Korea\"},{\"const\":\"KW\",\"title\":\"Kuwait\"},{\"const\":\"KG\",\"title\":\"Kyrgyzstan\"},{\"const\":\"LA\",\"title\":\"Lao People's Democratic Republic\"},{\"const\":\"LV\",\"title\":\"Latvia\"},{\"const\":\"LB\",\"title\":\"Lebanon\"},{\"const\":\"LS\",\"title\":\"Lesotho\"},{\"const\":\"LR\",\"title\":\"Liberia\"},{\"const\":\"LY\",\"title\":\"Libyan Arab Jamahiriya\"},{\"const\":\"LI\",\"title\":\"Liechtenstein\"},{\"const\":\"LT\",\"title\":\"Lithuania\"},{\"const\":\"LU\",\"title\":\"Luxembourg\"},{\"const\":\"MO\",\"title\":\"Macao\"},{\"const\":\"MK\",\"title\":\"Macedonia\"},{\"const\":\"MG\",\"title\":\"Madagascar\"},{\"const\":\"MW\",\"title\":\"Malawi\"},{\"const\":\"MY\",\"title\":\"Malaysia\"},{\"const\":\"MV\",\"title\":\"Maldives\"},{\"const\":\"ML\",\"title\":\"Mali\"},{\"const\":\"MT\",\"title\":\"Malta\"},{\"const\":\"MH\",\"title\":\"Marshall Islands\"},{\"const\":\"MQ\",\"title\":\"Martinique\"},{\"const\":\"MR\",\"title\":\"Mauritania\"},{\"const\":\"MU\",\"title\":\"Mauritius\"},{\"const\":\"YT\",\"title\":\"Mayotte\"},{\"const\":\"MX\",\"title\":\"Mexico\"},{\"const\":\"FM\",\"title\":\"Micronesia, Federated States Of\"},{\"const\":\"MD\",\"title\":\"Moldova\"},{\"const\":\"MC\",\"title\":\"Monaco\"},{\"const\":\"MN\",\"title\":\"Mongolia\"},{\"const\":\"ME\",\"title\":\"Montenegro\"},{\"const\":\"MS\",\"title\":\"Montserrat\"},{\"const\":\"MA\",\"title\":\"Morocco\"},{\"const\":\"MZ\",\"title\":\"Mozambique\"},{\"const\":\"MM\",\"title\":\"Myanmar\"},{\"const\":\"NA\",\"title\":\"Namibia\"},{\"const\":\"NR\",\"title\":\"Nauru\"},{\"const\":\"NP\",\"title\":\"Nepal\"},{\"const\":\"NL\",\"title\":\"Netherlands\"},{\"const\":\"NC\",\"title\":\"New Caledonia\"},{\"const\":\"NZ\",\"title\":\"New Zealand\"},{\"const\":\"NI\",\"title\":\"Nicaragua\"},{\"const\":\"NE\",\"title\":\"Niger\"},{\"const\":\"NG\",\"title\":\"Nigeria\"},{\"const\":\"NU\",\"title\":\"Niue\"},{\"const\":\"NF\",\"title\":\"Norfolk Island\"},{\"const\":\"MP\",\"title\":\"Northern Mariana Islands\"},{\"const\":\"NO\",\"title\":\"Norway\"},{\"const\":\"OM\",\"title\":\"Oman\"},{\"const\":\"PK\",\"title\":\"Pakistan\"},{\"const\":\"PW\",\"title\":\"Palau\"},{\"const\":\"PS\",\"title\":\"Palestinian Territory, Occupied\"},{\"const\":\"PA\",\"title\":\"Panama\"},{\"const\":\"PG\",\"title\":\"Papua New Guinea\"},{\"const\":\"PY\",\"title\":\"Paraguay\"},{\"const\":\"PE\",\"title\":\"Peru\"},{\"const\":\"PH\",\"title\":\"Philippines\"},{\"const\":\"PN\",\"title\":\"Pitcairn\"},{\"const\":\"PL\",\"title\":\"Poland\"},{\"const\":\"PT\",\"title\":\"Portugal\"},{\"const\":\"PR\",\"title\":\"Puerto Rico\"},{\"const\":\"QA\",\"title\":\"Qatar\"},{\"const\":\"RE\",\"title\":\"Reunion\"},{\"const\":\"RO\",\"title\":\"Romania\"},{\"const\":\"RU\",\"title\":\"Russian Federation\"},{\"const\":\"RW\",\"title\":\"Rwanda\"},{\"const\":\"BL\",\"title\":\"Saint Barthelemy\"},{\"const\":\"SH\",\"title\":\"Saint Helena\"},{\"const\":\"KN\",\"title\":\"Saint Kitts And Nevis\"},{\"const\":\"LC\",\"title\":\"Saint Lucia\"},{\"const\":\"MF\",\"title\":\"Saint Martin\"},{\"const\":\"PM\",\"title\":\"Saint Pierre And Miquelon\"},{\"const\":\"VC\",\"title\":\"Saint Vincent And Grenadines\"},{\"const\":\"WS\",\"title\":\"Samoa\"},{\"const\":\"SM\",\"title\":\"San Marino\"},{\"const\":\"ST\",\"title\":\"Sao Tome And Principe\"},{\"const\":\"SA\",\"title\":\"Saudi Arabia\"},{\"const\":\"SN\",\"title\":\"Senegal\"},{\"const\":\"RS\",\"title\":\"Serbia\"},{\"const\":\"SC\",\"title\":\"Seychelles\"},{\"const\":\"SL\",\"title\":\"Sierra Leone\"},{\"const\":\"SG\",\"title\":\"Singapore\"},{\"const\":\"SK\",\"title\":\"Slovakia\"},{\"const\":\"SI\",\"title\":\"Slovenia\"},{\"const\":\"SB\",\"title\":\"Solomon Islands\"},{\"const\":\"SO\",\"title\":\"Somalia\"},{\"const\":\"ZA\",\"title\":\"South Africa\"},{\"const\":\"ES\",\"title\":\"Spain\"},{\"const\":\"LK\",\"title\":\"Sri Lanka\"},{\"const\":\"SD\",\"title\":\"Sudan\"},{\"const\":\"SR\",\"title\":\"Suriname\"},{\"const\":\"SZ\",\"title\":\"Swaziland\"},{\"const\":\"SE\",\"title\":\"Sweden\"},{\"const\":\"CH\",\"title\":\"Switzerland\"},{\"const\":\"SY\",\"title\":\"Syrian Arab Republic\"},{\"const\":\"TW\",\"title\":\"Taiwan\"},{\"const\":\"TJ\",\"title\":\"Tajikistan\"},{\"const\":\"TZ\",\"title\":\"Tanzania\"},{\"const\":\"TH\",\"title\":\"Thailand\"},{\"const\":\"TL\",\"title\":\"Timor-Leste\"},{\"const\":\"TG\",\"title\":\"Togo\"},{\"const\":\"TK\",\"title\":\"Tokelau\"},{\"const\":\"TO\",\"title\":\"Tonga\"},{\"const\":\"TT\",\"title\":\"Trinidad And Tobago\"},{\"const\":\"TN\",\"title\":\"Tunisia\"},{\"const\":\"TR\",\"title\":\"Turkey\"},{\"const\":\"TM\",\"title\":\"Turkmenistan\"},{\"const\":\"TV\",\"title\":\"Tuvalu\"},{\"const\":\"UG\",\"title\":\"Uganda\"},{\"const\":\"UA\",\"title\":\"Ukraine\"},{\"const\":\"AE\",\"title\":\"United Arab Emirates\"},{\"const\":\"GB\",\"title\":\"United Kingdom\"},{\"const\":\"US\",\"title\":\"United States\"},{\"const\":\"UY\",\"title\":\"Uruguay\"},{\"const\":\"UZ\",\"title\":\"Uzbekistan\"},{\"const\":\"VU\",\"title\":\"Vanuatu\"},{\"const\":\"VE\",\"title\":\"Venezuela\"},{\"const\":\"VN\",\"title\":\"Vietnam\"},{\"const\":\"EH\",\"title\":\"Western Sahara\"},{\"const\":\"YE\",\"title\":\"Yemen\"},{\"const\":\"ZM\",\"title\":\"Zambia\"},{\"const\":\"ZW\",\"title\":\"Zimbabwe\"}]}},\"ban\":{\"title\":\"Ban\",\"description\":\"Ban players from the server when they are detected. When false, players will be kicked instead.\",\"type\":\"boolean\",\"default\":true},\"banDuration\":{\"title\":\"Ban duration\",\"description\":\"Duration of the ban.\",\"x-component\":\"duration\",\"type\":\"number\",\"minimum\":0,\"default\":86400000},\"message\":{\"title\":\"Message\",\"type\":\"string\",\"description\":\"Message to send to the player when they are kicked or banned.\",\"default\":\"Your IP address is banned.\"}},\"required\":[\"countries\"],\"additionalProperties\":false}",
637
+ "uiSchema": "{\"banDuration\":{\"ui:widget\":\"duration\"}}",
638
+ "permissions": [
639
+ {
640
+ "permission": "GEOBLOCK_IMMUNITY",
641
+ "friendlyName": "GeoBlock immunity",
642
+ "description": "Players with this permission will not be kicked or banned by GeoBlock.",
643
+ "canHaveCount": false
644
+ }
645
+ ],
646
+ "hooks": [
647
+ {
648
+ "eventType": "player-new-ip-detected",
649
+ "name": "IPDetected",
650
+ "function": "import { takaro, data, checkPermission } from '@takaro/helpers';\nasync function main() {\n const { gameServerId, player, pog } = data;\n const { country } = data.eventData;\n const { ban, banDuration, countries, message, mode } = data.module.userConfig;\n async function handleAction() {\n if (ban) {\n const now = new Date();\n const expiresAt = new Date(now.getTime() + banDuration * 1000);\n await takaro.player.banControllerCreate({\n gameServerId,\n playerId: player.id,\n until: expiresAt,\n reason: message,\n });\n }\n else {\n await takaro.gameserver.gameServerControllerKickPlayer(gameServerId, player.id, {\n reason: message,\n });\n }\n }\n const isImmune = checkPermission(pog, 'GEOBLOCK_IMMUNITY');\n if (isImmune) {\n console.log('Player has immunity, no action');\n return;\n }\n if (mode === 'allow') {\n if (countries.includes(country)) {\n console.log('Allowed country detected, no action');\n return;\n }\n console.log('Blocked country detected, performing actions');\n await handleAction();\n return;\n }\n if (mode === 'deny') {\n if (countries.includes(country)) {\n console.log('Blocked country detected, performing actions');\n await handleAction();\n return;\n }\n else {\n console.log('Allowed country detected, no action');\n return;\n }\n }\n}\nawait main();\n//# sourceMappingURL=IPDetected.js.map"
651
+ }
652
+ ]
653
+ }
654
+ ]
655
+ },
656
+ {
657
+ "name": "timedShutdown",
658
+ "author": "Takaro",
659
+ "supportedGames": [
660
+ "all"
661
+ ],
662
+ "versions": [
663
+ {
664
+ "tag": "0.0.1",
665
+ "description": "Automatically shut down the server at a specific time.",
666
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"warningMessage\":{\"type\":\"string\",\"title\":\"Warning message\",\"description\":\"Message to send to players before the server shuts down.\",\"default\":\"Server is shutting down in 5 minutes!\",\"minLength\":1,\"maxLength\":1024}},\"required\":[\"warningMessage\"]}",
667
+ "cronJobs": [
668
+ {
669
+ "name": "Shutdown",
670
+ "temporalValue": "30 3 * * *",
671
+ "function": "import { data, takaro } from '@takaro/helpers';\nasync function main() {\n const { gameServerId } = data;\n await takaro.gameserver.gameServerControllerShutdown(gameServerId);\n}\nawait main();\n//# sourceMappingURL=Shutdown.js.map"
672
+ },
673
+ {
674
+ "name": "warning",
675
+ "temporalValue": "25 3 * * *",
676
+ "function": "import { data, takaro } from '@takaro/helpers';\nasync function main() {\n const { gameServerId } = data;\n const msg = data.module.userConfig.warningMessage;\n await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n message: msg,\n });\n}\nawait main();\n//# sourceMappingURL=warning.js.map"
677
+ }
678
+ ]
679
+ }
680
+ ]
681
+ },
682
+ {
683
+ "name": "dailyRewards",
684
+ "author": "Takaro",
685
+ "supportedGames": [
686
+ "all"
687
+ ],
688
+ "versions": [
689
+ {
690
+ "description": "Provides daily login rewards with streak tracking",
691
+ "tag": "0.0.2",
692
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"baseReward\":{\"type\":\"number\",\"title\":\"Base Reward\",\"description\":\"Base amount of currency given for daily rewards. This is multiplied by streak level.\",\"default\":100,\"minimum\":1},\"maxStreak\":{\"type\":\"number\",\"title\":\"Maximum Streak\",\"description\":\"Maximum streak level a player can reach\",\"default\":365,\"minimum\":1},\"milestoneRewards\":{\"type\":\"array\",\"title\":\"Milestone Rewards\",\"description\":\"Additional rewards for reaching certain streak milestones\",\"items\":{\"type\":\"object\",\"properties\":{\"days\":{\"type\":\"number\",\"description\":\"Days needed to reach milestone\",\"minimum\":1},\"reward\":{\"type\":\"number\",\"description\":\"Bonus reward amount\"},\"message\":{\"type\":\"string\",\"description\":\"Message to show when milestone is reached\"}}},\"default\":[{\"days\":7,\"reward\":1000,\"message\":\"You did it! 7 days in a row!\"},{\"days\":30,\"reward\":5000,\"message\":\"A whole month! You're on fire!\"},{\"days\":90,\"reward\":20000,\"message\":\"90 days! You're unstoppable!\"},{\"days\":180,\"reward\":50000,\"message\":\"Half a year! You're a legend!\"},{\"days\":365,\"reward\":150000,\"message\":\"365 days! You're a true champion!\"}]}},\"required\":[\"baseReward\",\"maxStreak\",\"milestoneRewards\"],\"additionalProperties\":false}",
693
+ "functions": [
694
+ {
695
+ "name": "utils",
696
+ "function": "import { takaro, checkPermission } from '@takaro/helpers';\nexport const DAILY_KEY = 'daily_timestamp';\nexport const STREAK_KEY = 'daily_streak';\nexport async function getMultiplier(pog) {\n const perm = checkPermission(pog, 'DAILY_REWARD_MULTIPLIER');\n if (perm)\n return perm.count;\n return 1;\n}\nexport async function getPlayerStreak(gameServerId, playerId, moduleId) {\n const streakRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [STREAK_KEY],\n gameServerId: [gameServerId],\n playerId: [playerId],\n moduleId: [moduleId],\n },\n });\n return streakRes.data.data.length ? parseInt(JSON.parse(streakRes.data.data[0].value)) : 0;\n}\nexport async function getLastClaim(gameServerId, playerId, moduleId) {\n const lastClaimRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [DAILY_KEY],\n gameServerId: [gameServerId],\n playerId: [playerId],\n moduleId: [moduleId],\n },\n });\n return lastClaimRes.data.data.length ? new Date(JSON.parse(lastClaimRes.data.data[0].value)) : null;\n}\n//# sourceMappingURL=utils.js.map"
697
+ }
698
+ ],
699
+ "permissions": [
700
+ {
701
+ "permission": "DAILY_CLAIM",
702
+ "friendlyName": "Claim Daily Rewards",
703
+ "description": "Allows the player to claim daily rewards",
704
+ "canHaveCount": false
705
+ },
706
+ {
707
+ "permission": "DAILY_REWARD_MULTIPLIER",
708
+ "friendlyName": "Multiplier",
709
+ "description": "Control the multiplier per role. This is useful to give your donors a little extra. Count is an integer multiplier.",
710
+ "canHaveCount": true
711
+ }
712
+ ],
713
+ "commands": [
714
+ {
715
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nimport { DAILY_KEY, STREAK_KEY, getMultiplier } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n // Get last claim time\n const lastClaimRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [DAILY_KEY],\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n });\n const now = new Date();\n let streak = 1;\n if (lastClaimRes.data.data.length > 0) {\n const lastClaim = new Date(JSON.parse(lastClaimRes.data.data[0].value));\n const hoursSinceLastClaim = (now - lastClaim) / (1000 * 60 * 60);\n // Check if 24 hours have passed\n if (hoursSinceLastClaim < 24) {\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n throw new TakaroUserError(`You can claim your next reward at ${nextClaimTime.toLocaleString()}`);\n }\n // Get current streak\n const streakRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [STREAK_KEY],\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n });\n if (streakRes.data.data.length > 0) {\n // If claimed within 48 hours, increment streak\n if (hoursSinceLastClaim < 48) {\n streak = Math.min(JSON.parse(streakRes.data.data[0].value) + 1, mod.userConfig.maxStreak);\n await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, {\n value: JSON.stringify(streak),\n });\n }\n else {\n // Reset streak if more than 48 hours\n await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, {\n value: JSON.stringify(1),\n });\n }\n }\n else {\n // Create new streak record\n await takaro.variable.variableControllerCreate({\n key: STREAK_KEY,\n value: JSON.stringify(1),\n gameServerId,\n playerId: pog.playerId,\n moduleId: mod.moduleId,\n });\n }\n // Update last claim time\n await takaro.variable.variableControllerUpdate(lastClaimRes.data.data[0].id, {\n value: JSON.stringify(now),\n });\n }\n else {\n // First time claim\n await takaro.variable.variableControllerCreate({\n key: DAILY_KEY,\n value: JSON.stringify(now),\n gameServerId,\n playerId: pog.playerId,\n moduleId: mod.moduleId,\n });\n await takaro.variable.variableControllerCreate({\n key: STREAK_KEY,\n value: JSON.stringify(1),\n gameServerId,\n playerId: pog.playerId,\n moduleId: mod.moduleId,\n });\n }\n const multiplier = await getMultiplier(pog);\n const baseReward = mod.userConfig.baseReward * streak * multiplier;\n let bonusReward = 0;\n let milestoneMessage = '';\n // Check for milestones\n for (const milestone of mod.userConfig.milestoneRewards) {\n if (streak === milestone.days) {\n bonusReward = milestone.reward;\n milestoneMessage = `\\n${milestone.message}`;\n break;\n }\n }\n // Award total rewards\n const totalReward = baseReward + bonusReward;\n await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(gameServerId, pog.playerId, {\n currency: totalReward,\n });\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', gameServerId)).data.data.value;\n await pog.pm(`Daily reward claimed! You received ${totalReward} ${currencyName}\\n` +\n `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x bonus!)` : ''}` +\n milestoneMessage);\n}\nawait main();\n//# sourceMappingURL=daily.js.map",
716
+ "name": "daily",
717
+ "trigger": "daily",
718
+ "helpText": "Claim your daily reward",
719
+ "requiredPermissions": [
720
+ "DAILY_CLAIM"
721
+ ],
722
+ "arguments": []
723
+ },
724
+ {
725
+ "function": "import { data, takaro } from '@takaro/helpers';\nimport { getPlayerStreak, getLastClaim, getMultiplier } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const streak = await getPlayerStreak(gameServerId, pog.playerId, mod.moduleId);\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n const multiplier = await getMultiplier(pog);\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n if (!streak || !lastClaim) {\n await pog.pm(`You haven't claimed any daily rewards yet! Use ${prefix}daily to get started.`);\n return;\n }\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n const now = new Date();\n const canClaim = now >= nextClaimTime;\n // Find next milestone\n let nextMilestone = null;\n for (const milestone of mod.userConfig.milestoneRewards) {\n if (milestone.days > streak) {\n nextMilestone = milestone;\n break;\n }\n }\n let message = `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x donor bonus!)` : ''}\\n`;\n message += canClaim\n ? `Your daily reward is available! Use ${prefix}daily to claim it!\\n`\n : `Next reward available at: ${nextClaimTime.toLocaleString()}\\n`;\n if (nextMilestone) {\n message += `\\n🎯 Next milestone: ${nextMilestone.days} days (${nextMilestone.days - streak} days to go!)`;\n }\n await pog.pm(message);\n}\nawait main();\n//# sourceMappingURL=streak.js.map",
726
+ "name": "streak",
727
+ "trigger": "streak",
728
+ "helpText": "Check your current daily reward streak and next claim time",
729
+ "arguments": []
730
+ },
731
+ {
732
+ "function": "import { takaro, data } from '@takaro/helpers';\nimport { STREAK_KEY } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod, arguments: args } = data;\n // Limit count to reasonable number\n const count = Math.min(Math.max(1, args.count), 50);\n // Get all streaks\n const streaksRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [STREAK_KEY],\n gameServerId: [gameServerId],\n moduleId: [mod.moduleId],\n },\n limit: 1000, // Get all possible streaks\n });\n if (streaksRes.data.data.length === 0) {\n await pog.pm('No players have started their daily streak yet!');\n return;\n }\n // Sort by streak value\n const sortedStreaks = streaksRes.data.data\n .map((record) => ({\n playerId: record.playerId,\n streak: JSON.parse(record.value),\n }))\n .sort((a, b) => b.streak - a.streak)\n .slice(0, count);\n // Get player names\n const playerDetails = await Promise.all(sortedStreaks.map(async (record) => {\n const player = (await takaro.player.playerControllerGetOne(record.playerId)).data.data;\n return {\n name: player.name,\n streak: record.streak,\n };\n }));\n // Build message\n let message = `Top ${count} Daily Streaks:\\n\\n`;\n playerDetails.forEach((player, index) => {\n message += `${index + 1}. ${player.name}: ${player.streak} days\\n`;\n });\n await pog.pm(message);\n}\nawait main();\n//# sourceMappingURL=topstreak.js.map",
733
+ "name": "topstreak",
734
+ "trigger": "topstreak",
735
+ "helpText": "Shows the players with highest daily reward streaks",
736
+ "arguments": [
737
+ {
738
+ "name": "count",
739
+ "type": "number",
740
+ "defaultValue": "5",
741
+ "helpText": "Number of players to show (max 25)",
742
+ "position": 0
743
+ }
744
+ ]
745
+ }
746
+ ],
747
+ "hooks": [
748
+ {
749
+ "eventType": "player-connected",
750
+ "name": "dailyLoginCheck",
751
+ "function": "import { data, takaro } from '@takaro/helpers';\nimport { getLastClaim } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n // First time player\n if (!lastClaim) {\n await pog.pm(`Welcome! Use ${prefix}daily to claim your first daily reward and start your streak!`);\n return;\n }\n const now = new Date();\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n if (now >= nextClaimTime) {\n await pog.pm(`Your daily reward is ready! Use ${prefix}daily to claim it!`);\n }\n}\nawait main();\n//# sourceMappingURL=dailyLoginCheck.js.map"
752
+ }
753
+ ]
754
+ }
755
+ ]
756
+ }
757
+ ]