@takaro/modules 0.0.1

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 (227) hide show
  1. package/README.md +3 -0
  2. package/dist/BuiltinModule.d.ts +49 -0
  3. package/dist/BuiltinModule.js +194 -0
  4. package/dist/BuiltinModule.js.map +1 -0
  5. package/dist/dto/base.d.ts +6 -0
  6. package/dist/dto/base.js +28 -0
  7. package/dist/dto/base.js.map +1 -0
  8. package/dist/dto/discordEvents.d.ts +31 -0
  9. package/dist/dto/discordEvents.js +92 -0
  10. package/dist/dto/discordEvents.js.map +1 -0
  11. package/dist/dto/gameEvents.d.ts +84 -0
  12. package/dist/dto/gameEvents.js +190 -0
  13. package/dist/dto/gameEvents.js.map +1 -0
  14. package/dist/dto/index.d.ts +37 -0
  15. package/dist/dto/index.js +18 -0
  16. package/dist/dto/index.js.map +1 -0
  17. package/dist/dto/takaroEvents.d.ts +150 -0
  18. package/dist/dto/takaroEvents.js +422 -0
  19. package/dist/dto/takaroEvents.js.map +1 -0
  20. package/dist/main.d.ts +4 -0
  21. package/dist/main.js +31 -0
  22. package/dist/main.js.map +1 -0
  23. package/dist/modules/chatBridge/hooks/DiscordToGame.d.ts +1 -0
  24. package/dist/modules/chatBridge/hooks/DiscordToGame.js +18 -0
  25. package/dist/modules/chatBridge/hooks/DiscordToGame.js.map +1 -0
  26. package/dist/modules/chatBridge/hooks/GameToDiscord.d.ts +1 -0
  27. package/dist/modules/chatBridge/hooks/GameToDiscord.js +14 -0
  28. package/dist/modules/chatBridge/hooks/GameToDiscord.js.map +1 -0
  29. package/dist/modules/chatBridge/hooks/PlayerConnected.d.ts +1 -0
  30. package/dist/modules/chatBridge/hooks/PlayerConnected.js +9 -0
  31. package/dist/modules/chatBridge/hooks/PlayerConnected.js.map +1 -0
  32. package/dist/modules/chatBridge/hooks/PlayerDisconnected.d.ts +1 -0
  33. package/dist/modules/chatBridge/hooks/PlayerDisconnected.js +9 -0
  34. package/dist/modules/chatBridge/hooks/PlayerDisconnected.js.map +1 -0
  35. package/dist/modules/chatBridge/index.d.ts +4 -0
  36. package/dist/modules/chatBridge/index.js +54 -0
  37. package/dist/modules/chatBridge/index.js.map +1 -0
  38. package/dist/modules/economyUtils/commands/balance.d.ts +1 -0
  39. package/dist/modules/economyUtils/commands/balance.js +7 -0
  40. package/dist/modules/economyUtils/commands/balance.js.map +1 -0
  41. package/dist/modules/economyUtils/commands/confirmTransfer.d.ts +1 -0
  42. package/dist/modules/economyUtils/commands/confirmTransfer.js +38 -0
  43. package/dist/modules/economyUtils/commands/confirmTransfer.js.map +1 -0
  44. package/dist/modules/economyUtils/commands/grantCurrency.d.ts +1 -0
  45. package/dist/modules/economyUtils/commands/grantCurrency.js +31 -0
  46. package/dist/modules/economyUtils/commands/grantCurrency.js.map +1 -0
  47. package/dist/modules/economyUtils/commands/revokeCurrency.d.ts +1 -0
  48. package/dist/modules/economyUtils/commands/revokeCurrency.js +31 -0
  49. package/dist/modules/economyUtils/commands/revokeCurrency.js.map +1 -0
  50. package/dist/modules/economyUtils/commands/topCurrency.d.ts +1 -0
  51. package/dist/modules/economyUtils/commands/topCurrency.js +22 -0
  52. package/dist/modules/economyUtils/commands/topCurrency.js.map +1 -0
  53. package/dist/modules/economyUtils/commands/transfer.d.ts +1 -0
  54. package/dist/modules/economyUtils/commands/transfer.js +55 -0
  55. package/dist/modules/economyUtils/commands/transfer.js.map +1 -0
  56. package/dist/modules/economyUtils/index.d.ts +4 -0
  57. package/dist/modules/economyUtils/index.js +117 -0
  58. package/dist/modules/economyUtils/index.js.map +1 -0
  59. package/dist/modules/geoBlock/hooks/IPDetected.d.ts +1 -0
  60. package/dist/modules/geoBlock/hooks/IPDetected.js +50 -0
  61. package/dist/modules/geoBlock/hooks/IPDetected.js.map +1 -0
  62. package/dist/modules/geoBlock/index.d.ts +8 -0
  63. package/dist/modules/geoBlock/index.js +321 -0
  64. package/dist/modules/geoBlock/index.js.map +1 -0
  65. package/dist/modules/gimme/commands/gimme.d.ts +1 -0
  66. package/dist/modules/gimme/commands/gimme.js +23 -0
  67. package/dist/modules/gimme/commands/gimme.js.map +1 -0
  68. package/dist/modules/gimme/index.d.ts +4 -0
  69. package/dist/modules/gimme/index.js +43 -0
  70. package/dist/modules/gimme/index.js.map +1 -0
  71. package/dist/modules/highPingKicker/cronJobs/Ping check.d.ts +1 -0
  72. package/dist/modules/highPingKicker/cronJobs/Ping check.js +54 -0
  73. package/dist/modules/highPingKicker/cronJobs/Ping check.js.map +1 -0
  74. package/dist/modules/highPingKicker/index.d.ts +4 -0
  75. package/dist/modules/highPingKicker/index.js +34 -0
  76. package/dist/modules/highPingKicker/index.js.map +1 -0
  77. package/dist/modules/lottery/commands/buyTicket.d.ts +1 -0
  78. package/dist/modules/lottery/commands/buyTicket.js +54 -0
  79. package/dist/modules/lottery/commands/buyTicket.js.map +1 -0
  80. package/dist/modules/lottery/commands/nextDraw.d.ts +1 -0
  81. package/dist/modules/lottery/commands/nextDraw.js +34 -0
  82. package/dist/modules/lottery/commands/nextDraw.js.map +1 -0
  83. package/dist/modules/lottery/commands/viewTickets.d.ts +1 -0
  84. package/dist/modules/lottery/commands/viewTickets.js +23 -0
  85. package/dist/modules/lottery/commands/viewTickets.js.map +1 -0
  86. package/dist/modules/lottery/cronJobs/drawLottery.d.ts +1 -0
  87. package/dist/modules/lottery/cronJobs/drawLottery.js +96 -0
  88. package/dist/modules/lottery/cronJobs/drawLottery.js.map +1 -0
  89. package/dist/modules/lottery/index.d.ts +4 -0
  90. package/dist/modules/lottery/index.js +73 -0
  91. package/dist/modules/lottery/index.js.map +1 -0
  92. package/dist/modules/playerOnboarding/commands/starterkit.d.ts +1 -0
  93. package/dist/modules/playerOnboarding/commands/starterkit.js +34 -0
  94. package/dist/modules/playerOnboarding/commands/starterkit.js.map +1 -0
  95. package/dist/modules/playerOnboarding/hooks/playerConnected.d.ts +1 -0
  96. package/dist/modules/playerOnboarding/hooks/playerConnected.js +11 -0
  97. package/dist/modules/playerOnboarding/hooks/playerConnected.js.map +1 -0
  98. package/dist/modules/playerOnboarding/index.d.ts +4 -0
  99. package/dist/modules/playerOnboarding/index.js +51 -0
  100. package/dist/modules/playerOnboarding/index.js.map +1 -0
  101. package/dist/modules/serverMessages/cronJobs/Automated message.d.ts +1 -0
  102. package/dist/modules/serverMessages/cronJobs/Automated message.js +9 -0
  103. package/dist/modules/serverMessages/cronJobs/Automated message.js.map +1 -0
  104. package/dist/modules/serverMessages/index.d.ts +4 -0
  105. package/dist/modules/serverMessages/index.js +35 -0
  106. package/dist/modules/serverMessages/index.js.map +1 -0
  107. package/dist/modules/teleports/commands/deletetp.d.ts +1 -0
  108. package/dist/modules/teleports/commands/deletetp.js +20 -0
  109. package/dist/modules/teleports/commands/deletetp.js.map +1 -0
  110. package/dist/modules/teleports/commands/deletewaypoint.d.ts +1 -0
  111. package/dist/modules/teleports/commands/deletewaypoint.js +54 -0
  112. package/dist/modules/teleports/commands/deletewaypoint.js.map +1 -0
  113. package/dist/modules/teleports/commands/listwaypoints.d.ts +1 -0
  114. package/dist/modules/teleports/commands/listwaypoints.js +36 -0
  115. package/dist/modules/teleports/commands/listwaypoints.js.map +1 -0
  116. package/dist/modules/teleports/commands/setprivate.d.ts +1 -0
  117. package/dist/modules/teleports/commands/setprivate.js +31 -0
  118. package/dist/modules/teleports/commands/setprivate.js.map +1 -0
  119. package/dist/modules/teleports/commands/setpublic.d.ts +1 -0
  120. package/dist/modules/teleports/commands/setpublic.js +55 -0
  121. package/dist/modules/teleports/commands/setpublic.js.map +1 -0
  122. package/dist/modules/teleports/commands/settp.d.ts +1 -0
  123. package/dist/modules/teleports/commands/settp.js +42 -0
  124. package/dist/modules/teleports/commands/settp.js.map +1 -0
  125. package/dist/modules/teleports/commands/setwaypoint.d.ts +1 -0
  126. package/dist/modules/teleports/commands/setwaypoint.js +88 -0
  127. package/dist/modules/teleports/commands/setwaypoint.js.map +1 -0
  128. package/dist/modules/teleports/commands/teleport.d.ts +1 -0
  129. package/dist/modules/teleports/commands/teleport.js +74 -0
  130. package/dist/modules/teleports/commands/teleport.js.map +1 -0
  131. package/dist/modules/teleports/commands/teleportwaypoint.d.ts +1 -0
  132. package/dist/modules/teleports/commands/teleportwaypoint.js +50 -0
  133. package/dist/modules/teleports/commands/teleportwaypoint.js.map +1 -0
  134. package/dist/modules/teleports/commands/tplist.d.ts +1 -0
  135. package/dist/modules/teleports/commands/tplist.js +45 -0
  136. package/dist/modules/teleports/commands/tplist.js.map +1 -0
  137. package/dist/modules/teleports/functions/utils.d.ts +2 -0
  138. package/dist/modules/teleports/functions/utils.js +18 -0
  139. package/dist/modules/teleports/functions/utils.js.map +1 -0
  140. package/dist/modules/teleports/index.d.ts +4 -0
  141. package/dist/modules/teleports/index.js +184 -0
  142. package/dist/modules/teleports/index.js.map +1 -0
  143. package/dist/modules/utils/commands/help.d.ts +1 -0
  144. package/dist/modules/utils/commands/help.js +29 -0
  145. package/dist/modules/utils/commands/help.js.map +1 -0
  146. package/dist/modules/utils/commands/ping.d.ts +1 -0
  147. package/dist/modules/utils/commands/ping.js +6 -0
  148. package/dist/modules/utils/commands/ping.js.map +1 -0
  149. package/dist/modules/utils/index.d.ts +4 -0
  150. package/dist/modules/utils/index.js +35 -0
  151. package/dist/modules/utils/index.js.map +1 -0
  152. package/dist/modules.json +478 -0
  153. package/package.json +26 -0
  154. package/scripts/buildBuiltinJson.ts +14 -0
  155. package/src/BuiltinModule.ts +125 -0
  156. package/src/__tests__/aliases.integration.test.ts +54 -0
  157. package/src/__tests__/builtinmodule.unit.test.ts +13 -0
  158. package/src/__tests__/commandArgs.integration.test.ts +285 -0
  159. package/src/__tests__/economyUtils.integration.test.ts +488 -0
  160. package/src/__tests__/geoblock.integration.test.ts +380 -0
  161. package/src/__tests__/gimme.integration.test.ts +97 -0
  162. package/src/__tests__/help.integration.test.ts +133 -0
  163. package/src/__tests__/lottery.integration.test.ts +332 -0
  164. package/src/__tests__/modulePermission.integration.test.ts +192 -0
  165. package/src/__tests__/onboarding.integration.test.ts +123 -0
  166. package/src/__tests__/ping.integration.test.ts +36 -0
  167. package/src/__tests__/roleExpiry.integration.test.ts +74 -0
  168. package/src/__tests__/serverMessages.integration.test.ts +104 -0
  169. package/src/__tests__/systemConfigCost.integration.test.ts +196 -0
  170. package/src/__tests__/teleports/listtp.integration.test.ts +115 -0
  171. package/src/__tests__/teleports/publicteleports.integration.test.ts +350 -0
  172. package/src/__tests__/teleports/teleport.integration.test.ts +109 -0
  173. package/src/__tests__/teleports/tpManagement.integration.test.ts +175 -0
  174. package/src/__tests__/teleports/waypoints.integration.test.ts +613 -0
  175. package/src/dto/base.ts +13 -0
  176. package/src/dto/discordEvents.ts +69 -0
  177. package/src/dto/gameEvents.ts +154 -0
  178. package/src/dto/index.ts +25 -0
  179. package/src/dto/takaroEvents.ts +290 -0
  180. package/src/main.ts +36 -0
  181. package/src/modules/.eslintrc +5 -0
  182. package/src/modules/chatBridge/hooks/DiscordToGame.js +18 -0
  183. package/src/modules/chatBridge/hooks/GameToDiscord.js +18 -0
  184. package/src/modules/chatBridge/hooks/PlayerConnected.js +11 -0
  185. package/src/modules/chatBridge/hooks/PlayerDisconnected.js +11 -0
  186. package/src/modules/chatBridge/index.ts +59 -0
  187. package/src/modules/economyUtils/commands/balance.js +8 -0
  188. package/src/modules/economyUtils/commands/confirmTransfer.js +55 -0
  189. package/src/modules/economyUtils/commands/grantCurrency.js +38 -0
  190. package/src/modules/economyUtils/commands/revokeCurrency.js +38 -0
  191. package/src/modules/economyUtils/commands/topCurrency.js +29 -0
  192. package/src/modules/economyUtils/commands/transfer.js +73 -0
  193. package/src/modules/economyUtils/index.ts +125 -0
  194. package/src/modules/geoBlock/hooks/IPDetected.js +52 -0
  195. package/src/modules/geoBlock/index.ts +331 -0
  196. package/src/modules/gimme/commands/gimme.js +28 -0
  197. package/src/modules/gimme/index.ts +49 -0
  198. package/src/modules/highPingKicker/cronJobs/Ping check.js +66 -0
  199. package/src/modules/highPingKicker/index.ts +39 -0
  200. package/src/modules/lottery/commands/buyTicket.js +68 -0
  201. package/src/modules/lottery/commands/nextDraw.js +45 -0
  202. package/src/modules/lottery/commands/viewTickets.js +32 -0
  203. package/src/modules/lottery/cronJobs/drawLottery.js +124 -0
  204. package/src/modules/lottery/index.ts +80 -0
  205. package/src/modules/playerOnboarding/commands/starterkit.js +47 -0
  206. package/src/modules/playerOnboarding/hooks/playerConnected.js +14 -0
  207. package/src/modules/playerOnboarding/index.ts +58 -0
  208. package/src/modules/serverMessages/cronJobs/Automated message.js +12 -0
  209. package/src/modules/serverMessages/index.ts +40 -0
  210. package/src/modules/teleports/commands/deletetp.js +25 -0
  211. package/src/modules/teleports/commands/deletewaypoint.js +77 -0
  212. package/src/modules/teleports/commands/listwaypoints.js +55 -0
  213. package/src/modules/teleports/commands/setprivate.js +39 -0
  214. package/src/modules/teleports/commands/setpublic.js +71 -0
  215. package/src/modules/teleports/commands/settp.js +54 -0
  216. package/src/modules/teleports/commands/setwaypoint.js +112 -0
  217. package/src/modules/teleports/commands/teleport.js +93 -0
  218. package/src/modules/teleports/commands/teleportwaypoint.js +72 -0
  219. package/src/modules/teleports/commands/tplist.js +61 -0
  220. package/src/modules/teleports/functions/utils.js +20 -0
  221. package/src/modules/teleports/index.ts +193 -0
  222. package/src/modules/utils/commands/help.js +38 -0
  223. package/src/modules/utils/commands/ping.js +7 -0
  224. package/src/modules/utils/index.ts +40 -0
  225. package/tsconfig.build.json +10 -0
  226. package/tsconfig.json +9 -0
  227. package/typedoc.json +3 -0
@@ -0,0 +1,478 @@
1
+ [
2
+ {
3
+ "name": "utils",
4
+ "description": "A collection of useful commands",
5
+ "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"additionalProperties\":false}",
6
+ "uiSchema": "{}",
7
+ "commands": [
8
+ {
9
+ "function": "import { data } from '@takaro/helpers';\nasync function main() {\n await data.player.pm('Pong!');\n}\nawait main();\n//# sourceMappingURL=ping.js.map",
10
+ "name": "ping",
11
+ "trigger": "ping",
12
+ "helpText": "Replies with pong, useful for testing if the connection works.",
13
+ "arguments": []
14
+ },
15
+ {
16
+ "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\nasync function main() {\n const enabledModules = await takaro.gameserver.gameServerControllerGetInstalledModules(data.gameServerId);\n const moduleCommands = await Promise.all(enabledModules.data.data.map(async (mod) => {\n return (await takaro.module.moduleControllerGetOne(mod.moduleId)).data.data.commands;\n }));\n if (data.arguments.command === 'all') {\n await data.player.pm('Available commands:');\n for (const mod of moduleCommands) {\n await Promise.all(mod.map(async (command) => {\n await data.player.pm(`${command.name}: ${command.helpText}`);\n }));\n }\n }\n else {\n const allCommandsFlat = moduleCommands.flat();\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 await data.player.pm(`${requestedCommand.name}: ${requestedCommand.helpText}`);\n }\n }\n}\nawait main();\n//# sourceMappingURL=help.js.map",
17
+ "name": "help",
18
+ "trigger": "help",
19
+ "helpText": "The text you are reading right now, displays information about commands.",
20
+ "arguments": [
21
+ {
22
+ "name": "command",
23
+ "type": "string",
24
+ "defaultValue": "all",
25
+ "helpText": "The command to get help for",
26
+ "position": 0
27
+ }
28
+ ]
29
+ }
30
+ ],
31
+ "hooks": [],
32
+ "cronJobs": [],
33
+ "functions": [],
34
+ "permissions": []
35
+ },
36
+ {
37
+ "name": "teleports",
38
+ "description": "A set of commands to allow players to set their own teleport points and teleport to them.",
39
+ "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}",
40
+ "uiSchema": "{\"timeout\":{\"ui:widget\":\"duration\"}}",
41
+ "commands": [
42
+ {
43
+ "function": "import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';\nimport { findTp } from './utils.js';\nasync function main() {\n const { pog, gameServerId, arguments: args, module: mod } = data;\n if (!checkPermission(pog, 'TELEPORTS_USE')) {\n throw new TakaroUserError('You do not have permission to use teleports.');\n }\n const ownedTeleportRes = await findTp(args.tp, pog.playerId);\n let teleports = ownedTeleportRes.data.data;\n if (mod.userConfig.allowPublicTeleports) {\n const maybePublicTeleportRes = await findTp(args.tp);\n const publicTeleports = maybePublicTeleportRes.data.data.filter((tele) => {\n const teleport = JSON.parse(tele.value);\n return teleport.public;\n });\n teleports = teleports.concat(publicTeleports);\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 console.log(createRes);\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 });\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 });\n await data.player.pm(`Teleported to ${teleport.name}.`);\n}\nawait main();\n//# sourceMappingURL=teleport.js.map",
44
+ "name": "teleport",
45
+ "trigger": "tp",
46
+ "helpText": "Teleports to one of your set locations.",
47
+ "arguments": [
48
+ {
49
+ "name": "tp",
50
+ "type": "string",
51
+ "helpText": "The location to teleport to.",
52
+ "position": 0
53
+ }
54
+ ]
55
+ },
56
+ {
57
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data;\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: 'tp',\n },\n sortBy: 'key',\n sortDirection: 'asc',\n })).data.data;\n const maybePublicTeleports = (await takaro.variable.variableControllerSearch({\n filters: {\n gameServerId: [gameServerId],\n moduleId: [mod.moduleId],\n },\n search: {\n key: ['tp'],\n },\n sortBy: 'key',\n sortDirection: 'asc',\n })).data.data;\n const teleports = maybePublicTeleports.filter((tele) => {\n const teleport = JSON.parse(tele.value);\n const isPublic = teleport.public && teleport.playerId !== pog.playerId;\n const isOwned = ownedTeleports.find((t) => t.playerId === pog.playerId);\n return isPublic || isOwned;\n });\n if (teleports.length === 0) {\n await data.player.pm(`You have no teleports set, 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} ${teleport.public ? '(public)' : ''}`);\n }\n}\nawait main();\n//# sourceMappingURL=tplist.js.map",
58
+ "name": "tplist",
59
+ "trigger": "tplist",
60
+ "helpText": "Lists all your set locations."
61
+ },
62
+ {
63
+ "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 hasPermission = checkPermission(pog, 'TELEPORTS_USE');\n if (!hasPermission) {\n throw new TakaroUserError('You do not have permission to use teleports.');\n }\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n const existingVariable = await findTp(args.tp);\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 allPlayerTeleports = await takaro.variable.variableControllerSearch({\n search: {\n key: getVariableKey(''),\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 }),\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",
64
+ "name": "settp",
65
+ "trigger": "settp",
66
+ "helpText": "Sets a location to teleport to.",
67
+ "arguments": [
68
+ {
69
+ "name": "tp",
70
+ "type": "string",
71
+ "helpText": "The location name.",
72
+ "position": 0
73
+ }
74
+ ]
75
+ },
76
+ {
77
+ "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)],\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",
78
+ "name": "deletetp",
79
+ "trigger": "deletetp",
80
+ "helpText": "Deletes a location.",
81
+ "arguments": [
82
+ {
83
+ "name": "tp",
84
+ "type": "string",
85
+ "helpText": "The location name.",
86
+ "position": 0
87
+ }
88
+ ]
89
+ },
90
+ {
91
+ "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;\n if (!mod.userConfig.allowPublicTeleports) {\n throw new TakaroUserError('Public teleports are disabled.');\n }\n const hasPermission = checkPermission(pog, 'TELEPORTS_CREATE_PUBLIC');\n if (!hasPermission) {\n throw new TakaroUserError('You do not have permission to create public teleports.');\n }\n const existingTeleportsForPlayerRes = await takaro.variable.variableControllerSearch({\n search: {\n key: 'tp_',\n },\n filters: {\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n });\n const existingPublicTeleportsForPlayer = existingTeleportsForPlayerRes.data.data.filter((tp) => {\n const teleport = JSON.parse(tp.value);\n return teleport.public;\n });\n if (existingPublicTeleportsForPlayer.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 teleportRes = 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 });\n const teleports = teleportRes.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 value: JSON.stringify({\n ...teleport,\n public: true,\n }),\n });\n await data.player.pm(`Teleport ${args.tp} is now public.`);\n}\nawait main();\n//# sourceMappingURL=setpublic.js.map",
92
+ "name": "setpublic",
93
+ "trigger": "setpublic",
94
+ "helpText": "Sets a teleport to be public, allowing other players to teleport to it.",
95
+ "arguments": [
96
+ {
97
+ "name": "tp",
98
+ "type": "string",
99
+ "helpText": "The location name.",
100
+ "position": 0
101
+ }
102
+ ]
103
+ },
104
+ {
105
+ "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)],\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 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 value: JSON.stringify({\n ...teleport,\n public: false,\n }),\n });\n await data.player.pm(`Teleport ${args.tp} is now private.`);\n}\nawait main();\n//# sourceMappingURL=setprivate.js.map",
106
+ "name": "setprivate",
107
+ "trigger": "setprivate",
108
+ "helpText": "Sets a teleport to be private, only the teleport owner can teleport to it.",
109
+ "arguments": [
110
+ {
111
+ "name": "tp",
112
+ "type": "string",
113
+ "helpText": "The location name.",
114
+ "position": 0
115
+ }
116
+ ]
117
+ },
118
+ {
119
+ "function": "import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';\nfunction getWaypointName(name) {\n return `waypoint ${name}`;\n}\nasync function main() {\n const { pog, gameServerId, module: mod, arguments: args } = data;\n if (!checkPermission(pog, 'TELEPORTS_MANAGE_WAYPOINTS')) {\n throw new TakaroUserError('You do not have permission to manage waypoints.');\n }\n async function ensureWaypointsModule() {\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 description: 'Waypoints module for the teleport system.',\n })).data.data;\n }\n let waypointsInstallation = (await takaro.gameserver.gameServerControllerGetInstalledModules(gameServerId)).data.data.find((module) => module.name === 'Waypoints');\n if (!waypointsInstallation) {\n console.log('Waypoints module not found, installing it.');\n waypointsInstallation = (await takaro.gameserver.gameServerControllerInstallModule(gameServerId, waypointsDefinition.id)).data.data;\n }\n return { waypointsInstallation, waypointsDefinition };\n }\n const { waypointsInstallation, waypointsDefinition } = await ensureWaypointsModule();\n try {\n await takaro.variable.variableControllerCreate({\n moduleId: waypointsInstallation.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 }),\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 }\n const teleportCommand = await takaro.command.commandControllerSearch({\n filters: {\n moduleId: [mod.moduleId],\n name: ['teleportwaypoint'],\n },\n });\n await takaro.command.commandControllerCreate({\n moduleId: waypointsInstallation.moduleId,\n name: `waypoint ${args.waypoint} server ${gameServerId}`,\n trigger: args.waypoint,\n helpText: `Teleport to waypoint ${args.waypoint}.`,\n function: teleportCommand.data.data[0].function.code,\n });\n const existingPermissions = waypointsDefinition.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 const gameServer = (await takaro.gameserver.gameServerControllerGetOne(gameServerId)).data.data;\n await takaro.module.moduleControllerUpdate(waypointsInstallation.moduleId, {\n permissions: [\n {\n permission: `WAYPOINTS_USE_${args.waypoint.toUpperCase()}_${gameServerId}`,\n description: `Use the waypoint ${args.waypoint} on ${gameServer.name}.`,\n friendlyName: `Use waypoint ${args.waypoint} on ${gameServer.name}`,\n canHaveCount: false,\n },\n ...permissionInputDTOs,\n ],\n });\n // Need to reinstall the module to ensure the new commands systemconfig and permissions are properly in place\n await takaro.gameserver.gameServerControllerInstallModule(gameServerId, waypointsInstallation.moduleId, {\n systemConfig: JSON.stringify(waypointsInstallation.systemConfig),\n userConfig: JSON.stringify(waypointsInstallation.userConfig),\n });\n await pog.pm(`Waypoint ${args.waypoint} set.`);\n}\nawait main();\n//# sourceMappingURL=setwaypoint.js.map",
120
+ "name": "setwaypoint",
121
+ "trigger": "setwaypoint",
122
+ "helpText": "Creates a new waypoint.",
123
+ "arguments": [
124
+ {
125
+ "name": "waypoint",
126
+ "type": "string",
127
+ "helpText": "The location name.",
128
+ "position": 0
129
+ }
130
+ ]
131
+ },
132
+ {
133
+ "function": "import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';\nfunction getWaypointName(name) {\n return `waypoint ${name}`;\n}\nasync function main() {\n const { pog, gameServerId, arguments: args } = data;\n if (!checkPermission(pog, 'TELEPORTS_MANAGE_WAYPOINTS')) {\n throw new TakaroUserError('You do not have permission to manage waypoints.');\n }\n async function ensureWaypointsModule() {\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 description: 'Waypoints module for the teleport system.',\n })).data.data;\n }\n let waypointsInstallation = (await takaro.gameserver.gameServerControllerGetInstalledModules(gameServerId)).data.data.find((module) => module.name === 'Waypoints');\n if (!waypointsInstallation) {\n console.log('Waypoints module not found, installing it.');\n waypointsInstallation = (await takaro.gameserver.gameServerControllerInstallModule(gameServerId, waypointsDefinition.id)).data.data;\n }\n return { waypointsInstallation, waypointsDefinition };\n }\n const { waypointsInstallation } = await ensureWaypointsModule();\n const variable = await takaro.variable.variableControllerSearch({\n filters: {\n key: [getWaypointName(args.waypoint)],\n gameServerId: [gameServerId],\n moduleId: [waypointsInstallation.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 const teleportCommand = await takaro.command.commandControllerSearch({\n filters: {\n moduleId: [waypointsInstallation.moduleId],\n name: [`waypoint ${args.waypoint} server ${gameServerId}`],\n },\n });\n if (teleportCommand.data.data.length) {\n await takaro.command.commandControllerRemove(teleportCommand.data.data[0].id);\n }\n await pog.pm(`Waypoint ${args.waypoint} deleted.`);\n}\nawait main();\n//# sourceMappingURL=deletewaypoint.js.map",
134
+ "name": "deletewaypoint",
135
+ "trigger": "deletewaypoint",
136
+ "helpText": "Deletes a waypoint.",
137
+ "arguments": [
138
+ {
139
+ "name": "waypoint",
140
+ "type": "string",
141
+ "helpText": "The location name.",
142
+ "position": 0
143
+ }
144
+ ]
145
+ },
146
+ {
147
+ "function": "import { takaro, data, checkPermission } from '@takaro/helpers';\nasync function main() {\n const { pog, gameServerId } = data;\n async function ensureWaypointsModule() {\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 description: 'Waypoints module for the teleport system.',\n })).data.data;\n }\n let waypointsInstallation = (await takaro.gameserver.gameServerControllerGetInstalledModules(gameServerId)).data.data.find((module) => module.name === 'Waypoints');\n if (!waypointsInstallation) {\n console.log('Waypoints module not found, installing it.');\n waypointsInstallation = (await takaro.gameserver.gameServerControllerInstallModule(gameServerId, waypointsDefinition.id)).data.data;\n }\n return { waypointsInstallation, waypointsDefinition };\n }\n const { waypointsDefinition } = await ensureWaypointsModule();\n const allWaypoints = waypointsDefinition.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",
148
+ "name": "listwaypoints",
149
+ "trigger": "waypoints",
150
+ "helpText": "Lists all waypoints."
151
+ },
152
+ {
153
+ "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 } = data;\n if (!checkPermission(pog, `WAYPOINTS_USE_${trigger.toUpperCase()}_${gameServerId}`)) {\n throw new TakaroUserError(`You are not allowed to use the waypoint ${trigger}.`);\n }\n async function ensureWaypointsModule() {\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 description: 'Waypoints module for the teleport system.',\n })).data.data;\n }\n let waypointsInstallation = (await takaro.gameserver.gameServerControllerGetInstalledModules(gameServerId)).data.data.find((module) => module.name === 'Waypoints');\n if (!waypointsInstallation) {\n console.log('Waypoints module not found, installing it.');\n waypointsInstallation = (await takaro.gameserver.gameServerControllerInstallModule(gameServerId, waypointsDefinition.id)).data.data;\n }\n return { waypointsInstallation, waypointsDefinition };\n }\n const { waypointsInstallation } = await ensureWaypointsModule();\n const variable = await takaro.variable.variableControllerSearch({\n filters: {\n key: [getWaypointName(trigger)],\n gameServerId: [gameServerId],\n moduleId: [waypointsInstallation.moduleId],\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 });\n await pog.pm(`Teleported to waypoint ${trigger}.`);\n}\nawait main();\n//# sourceMappingURL=teleportwaypoint.js.map",
154
+ "name": "teleportwaypoint",
155
+ "trigger": "teleportwaypoint",
156
+ "helpText": "Placeholder command, this will not be used directly. The module will install aliases for this command corresponding to the waypoint names."
157
+ }
158
+ ],
159
+ "hooks": [],
160
+ "cronJobs": [],
161
+ "functions": [
162
+ {
163
+ "name": "utils",
164
+ "function": "import { takaro, data } from '@takaro/helpers';\nexport function getVariableKey(tpName) {\n return `tp_${tpName}`;\n}\nexport async function findTp(tpName, playerId) {\n const { gameServerId, module: mod } = data;\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}\n//# sourceMappingURL=utils.js.map"
165
+ }
166
+ ],
167
+ "permissions": [
168
+ {
169
+ "permission": "TELEPORTS_CREATE_PUBLIC",
170
+ "friendlyName": "Create Public Teleports",
171
+ "description": "Allows the player to create public teleports.",
172
+ "canHaveCount": false
173
+ },
174
+ {
175
+ "permission": "TELEPORTS_USE",
176
+ "friendlyName": "Use Teleports",
177
+ "description": "Allows the player to use teleports modules.",
178
+ "canHaveCount": false
179
+ },
180
+ {
181
+ "permission": "TELEPORTS_MANAGE_WAYPOINTS",
182
+ "friendlyName": "Manage waypoints",
183
+ "description": "Allows creating, deleting, and managing waypoints.",
184
+ "canHaveCount": false
185
+ }
186
+ ]
187
+ },
188
+ {
189
+ "name": "playerOnboarding",
190
+ "description": "Collection of functions that are executed when a player joins the server. Helps with onboarding new players, like sending a welcome message.",
191
+ "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\",\"x-component\":\"item\",\"title\":\"Starter kit items\",\"description\":\"List of items a player will receive when they execute the starterkit command for the first time.\",\"uniqueItems\":true,\"items\":{\"type\":\"string\"}}},\"required\":[],\"additionalProperties\":false}",
192
+ "uiSchema": "{\"starterKitItems\":{\"ui:widget\":\"item\"}}",
193
+ "commands": [
194
+ {
195
+ "name": "starterkit",
196
+ "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 await Promise.all(items.map(async (item) => {\n return takaro.gameserver.gameServerControllerGiveItem(data.gameServerId, data.player.id, {\n name: item,\n amount: 1,\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",
197
+ "trigger": "starterkit",
198
+ "helpText": "Get a starter kit, you can only execute this once on a server!"
199
+ }
200
+ ],
201
+ "hooks": [
202
+ {
203
+ "eventType": "player-connected",
204
+ "name": "playerConnected",
205
+ "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"
206
+ }
207
+ ],
208
+ "cronJobs": [],
209
+ "functions": [],
210
+ "permissions": []
211
+ },
212
+ {
213
+ "name": "serverMessages",
214
+ "description": "Send automated, rotated, configurable messages to players on the server.",
215
+ "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\"]}",
216
+ "uiSchema": "{}",
217
+ "commands": [],
218
+ "hooks": [],
219
+ "cronJobs": [
220
+ {
221
+ "name": "Automated message",
222
+ "temporalValue": "*/30 * * * *",
223
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const randomMessage = data.module.userConfig.messages[Math.floor(Math.random() * data.module.userConfig.messages.length)];\n await takaro.gameserver.gameServerControllerSendMessage(data.gameServerId, {\n message: randomMessage,\n });\n}\nawait main();\n//# sourceMappingURL=Automated%20message.js.map"
224
+ }
225
+ ],
226
+ "functions": [],
227
+ "permissions": []
228
+ },
229
+ {
230
+ "name": "chatBridge",
231
+ "description": "Connect chat to other services like Discord.",
232
+ "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}",
233
+ "uiSchema": "{}",
234
+ "commands": [],
235
+ "hooks": [
236
+ {
237
+ "eventType": "discord-message",
238
+ "name": "DiscordToGame",
239
+ "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"
240
+ },
241
+ {
242
+ "eventType": "chat-message",
243
+ "name": "GameToDiscord",
244
+ "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 Discord channel ID'];\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"
245
+ },
246
+ {
247
+ "eventType": "player-connected",
248
+ "name": "PlayerConnected",
249
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const discordChannel = data.module.systemConfig.hooks['DiscordToGame Discord channel ID'];\n await takaro.discord.discordControllerSendMessage(discordChannel, {\n message: `[🔌 Connected]: ${data.player.name}`,\n });\n}\nawait main();\n//# sourceMappingURL=PlayerConnected.js.map"
250
+ },
251
+ {
252
+ "eventType": "player-disconnected",
253
+ "name": "PlayerDisconnected",
254
+ "function": "import { takaro, data } from '@takaro/helpers';\nasync function main() {\n const discordChannel = data.module.systemConfig.hooks['DiscordToGame Discord channel ID'];\n await takaro.discord.discordControllerSendMessage(discordChannel, {\n message: `[👋 Disconnected]: ${data.player.name}`,\n });\n}\nawait main();\n//# sourceMappingURL=PlayerDisconnected.js.map"
255
+ }
256
+ ],
257
+ "cronJobs": [],
258
+ "functions": [],
259
+ "permissions": []
260
+ },
261
+ {
262
+ "name": "gimme",
263
+ "description": "Randomly selects an item from a list of items.",
264
+ "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\":\"string\"}},\"commands\":{\"title\":\"Commands\",\"type\":\"array\",\"default\":[\"say hello from gimme\"],\"items\":{\"type\":\"string\"}}},\"required\":[\"items\"],\"additionalProperties\":false}",
265
+ "uiSchema": "{\"items\":{\"ui:widget\":\"item\"}}",
266
+ "commands": [
267
+ {
268
+ "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 await takaro.gameserver.gameServerControllerGiveItem(data.gameServerId, data.player.id, {\n name: randomOption,\n amount: 1,\n });\n await data.player.pm(`You received ${randomOption}!`);\n }\n else {\n await takaro.gameserver.gameServerControllerExecuteCommand(data.gameServerId, { command: randomOption });\n }\n}\nawait main();\n//# sourceMappingURL=gimme.js.map",
269
+ "name": "gimme",
270
+ "trigger": "gimme",
271
+ "helpText": "Randomly selects item from a list of items and entities."
272
+ }
273
+ ],
274
+ "hooks": [],
275
+ "cronJobs": [],
276
+ "functions": [],
277
+ "permissions": []
278
+ },
279
+ {
280
+ "name": "highPingKicker",
281
+ "description": "Automatically kick players with high ping, with warnings and configurable thresholds.",
282
+ "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\":[]}",
283
+ "uiSchema": "{}",
284
+ "commands": [],
285
+ "hooks": [],
286
+ "cronJobs": [
287
+ {
288
+ "name": "Ping check",
289
+ "temporalValue": "*/5 * * * *",
290
+ "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.variableControllerFind({\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);\n }\n if (currentWarningsRecords.length === 1) {\n await takaro.variable.variableControllerUpdate(currentWarningsRecords[0].id, {\n value: (currentWarnings + 1).toString(),\n });\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 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 await takaro.variable.variableControllerDelete(currentWarningsRecords[0].id);\n }\n }\n }));\n}\nawait main();\n//# sourceMappingURL=Ping%20check.js.map"
291
+ }
292
+ ],
293
+ "functions": [],
294
+ "permissions": []
295
+ },
296
+ {
297
+ "name": "economyUtils",
298
+ "description": "A set of commands to allow players to manage their currency.",
299
+ "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}},\"required\":[],\"additionalProperties\":false}",
300
+ "uiSchema": "{}",
301
+ "commands": [
302
+ {
303
+ "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",
304
+ "name": "balance",
305
+ "trigger": "balance",
306
+ "helpText": "Check your balance.",
307
+ "arguments": []
308
+ },
309
+ {
310
+ "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",
311
+ "name": "topCurrency",
312
+ "trigger": "topcurrency",
313
+ "helpText": "List of the 10 players with the highest balance.",
314
+ "arguments": []
315
+ },
316
+ {
317
+ "function": "import { takaro, data, checkPermission, TakaroUserError } 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 if (!checkPermission(granter, 'ECONOMY_UTILS_MANAGE_CURRENCY')) {\n throw new TakaroUserError('You do not have permission to use grant currency command.');\n }\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",
318
+ "name": "grantCurrency",
319
+ "trigger": "grantcurrency",
320
+ "helpText": "Grant money to a player. The money is not taken from your own balance but is new currency.",
321
+ "arguments": [
322
+ {
323
+ "name": "receiver",
324
+ "type": "player",
325
+ "helpText": "The player to grant currency to.",
326
+ "position": 0
327
+ },
328
+ {
329
+ "name": "amount",
330
+ "type": "number",
331
+ "helpText": "The amount of money.",
332
+ "position": 1
333
+ }
334
+ ]
335
+ },
336
+ {
337
+ "function": "import { takaro, data, checkPermission, TakaroUserError } 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 if (!checkPermission(revoker, 'ECONOMY_UTILS_MANAGE_CURRENCY')) {\n throw new TakaroUserError('You do not have permission to use revoke currency command.');\n }\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",
338
+ "name": "revokeCurrency",
339
+ "trigger": "revokecurrency",
340
+ "helpText": "Grant money to a player. The money is not taken from your own balance but is new currency.",
341
+ "arguments": [
342
+ {
343
+ "name": "receiver",
344
+ "type": "player",
345
+ "helpText": "The player to revoke currency from.",
346
+ "position": 0
347
+ },
348
+ {
349
+ "name": "amount",
350
+ "type": "number",
351
+ "helpText": "The amount of money.",
352
+ "position": 1
353
+ }
354
+ ]
355
+ },
356
+ {
357
+ "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,\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",
358
+ "name": "confirmTransfer",
359
+ "trigger": "confirmtransfer",
360
+ "helpText": "Confirms a pending transfer."
361
+ },
362
+ {
363
+ "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 (e) {\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",
364
+ "name": "transfer",
365
+ "trigger": "transfer",
366
+ "helpText": "Transfer money to another player.",
367
+ "arguments": [
368
+ {
369
+ "name": "receiver",
370
+ "type": "player",
371
+ "helpText": "The player to transfer money to.",
372
+ "position": 0
373
+ },
374
+ {
375
+ "name": "amount",
376
+ "type": "number",
377
+ "helpText": "The amount of money to transfer.",
378
+ "position": 1
379
+ }
380
+ ]
381
+ }
382
+ ],
383
+ "hooks": [],
384
+ "cronJobs": [],
385
+ "functions": [],
386
+ "permissions": [
387
+ {
388
+ "permission": "ECONOMY_UTILS_MANAGE_CURRENCY",
389
+ "friendlyName": "Manage currency",
390
+ "description": "Allows players to manage currency of other players. This includes granting and revoking currency.",
391
+ "canHaveCount": false
392
+ }
393
+ ]
394
+ },
395
+ {
396
+ "name": "lottery",
397
+ "description": "Players can buy tickets for a lottery, and the winner is chosen at random.",
398
+ "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}",
399
+ "uiSchema": "{}",
400
+ "commands": [
401
+ {
402
+ "function": "import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';\nasync function main() {\n const { pog, gameServerId, arguments: args, module: mod } = data;\n const varKey = 'lottery_tickets_bought';\n if (!checkPermission(pog, 'LOTTERY_BUY')) {\n throw new TakaroUserError('You do not have permission to buy lottery tickets.');\n }\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",
403
+ "name": "buyTicket",
404
+ "trigger": "buyTicket",
405
+ "helpText": "Buy a lottery ticket.",
406
+ "arguments": [
407
+ {
408
+ "name": "amount",
409
+ "type": "number",
410
+ "helpText": "The amount of tickets to buy.",
411
+ "position": 0
412
+ }
413
+ ]
414
+ },
415
+ {
416
+ "function": "import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const varKey = 'lottery_tickets_bought';\n if (!checkPermission(pog, 'LOTTERY_VIEW_TICKETS')) {\n throw new TakaroUserError('You do not have permission to view lottery tickets.');\n }\n const tickets = (await takaro.variable.variableControllerSearch({\n filters: {\n gameServerId,\n key: varKey,\n moduleId: mod.id,\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",
417
+ "name": "viewTickets",
418
+ "trigger": "viewTickets",
419
+ "helpText": "View your lottery tickets.",
420
+ "arguments": []
421
+ },
422
+ {
423
+ "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)}`);\n}\nawait main();\n//# sourceMappingURL=nextDraw.js.map",
424
+ "name": "nextDraw",
425
+ "trigger": "nextDraw",
426
+ "helpText": "View when the next draw is.",
427
+ "arguments": []
428
+ }
429
+ ],
430
+ "hooks": [],
431
+ "cronJobs": [
432
+ {
433
+ "name": "drawLottery",
434
+ "temporalValue": "0 0 * * *",
435
+ "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"
436
+ }
437
+ ],
438
+ "functions": [],
439
+ "permissions": [
440
+ {
441
+ "permission": "LOTTERY_BUY",
442
+ "friendlyName": "Buy Lottery Tickets",
443
+ "canHaveCount": false,
444
+ "description": "Allows the player to buy lottery tickets."
445
+ },
446
+ {
447
+ "permission": "LOTTERY_VIEW_TICKETS",
448
+ "friendlyName": "View Lottery Tickets",
449
+ "description": "Allows the player to view his lottery tickets.",
450
+ "canHaveCount": false
451
+ }
452
+ ]
453
+ },
454
+ {
455
+ "name": "geoBlock",
456
+ "description": "Block players from certain countries from joining the server.",
457
+ "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 country\",\"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}",
458
+ "uiSchema": "{\"banDuration\":{\"ui:widget\":\"duration\"}}",
459
+ "commands": [],
460
+ "hooks": [
461
+ {
462
+ "eventType": "player-new-ip-detected",
463
+ "name": "IPDetected",
464
+ "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.gameserver.gameServerControllerBanPlayer(gameServerId, player.id, {\n reason: message,\n expiresAt,\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 else {\n console.log('Blocked country detected, performing actions');\n await handleAction();\n return;\n }\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"
465
+ }
466
+ ],
467
+ "cronJobs": [],
468
+ "functions": [],
469
+ "permissions": [
470
+ {
471
+ "permission": "GEOBLOCK_IMMUNITY",
472
+ "friendlyName": "GeoBlock immunity",
473
+ "description": "Players with this permission will not be kicked or banned by GeoBlock.",
474
+ "canHaveCount": false
475
+ }
476
+ ]
477
+ }
478
+ ]