{
  "name": "teleports",
  "author": "Takaro",
  "supportedGames": [
    "7 days to die",
    "rust",
    "minecraft"
  ],
  "takaroVersion": ">=0.0.1",
  "versions": [
    {
      "tag": "0.0.4",
      "description": "A set of commands to allow players to set their own teleport points and teleport to them.",
      "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}",
      "uiSchema": "{\"timeout\":{\"ui:widget\":\"duration\"}}",
      "commands": [
        {
          "name": "teleport",
          "trigger": "tp",
          "helpText": "Teleports to one of your set locations.",
          "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 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        else {\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        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",
          "arguments": [
            {
              "name": "tp",
              "type": "string",
              "helpText": "The location to teleport to.",
              "position": 0
            }
          ]
        },
        {
          "name": "tplist",
          "trigger": "tplist",
          "helpText": "Lists all your set locations.",
          "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",
          "arguments": []
        },
        {
          "name": "settp",
          "trigger": "settp",
          "helpText": "Sets a location to teleport to.",
          "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",
          "arguments": [
            {
              "name": "tp",
              "type": "string",
              "helpText": "The location name.",
              "position": 0
            }
          ]
        },
        {
          "name": "deletetp",
          "trigger": "deletetp",
          "helpText": "Deletes a location.",
          "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",
          "arguments": [
            {
              "name": "tp",
              "type": "string",
              "helpText": "The location name.",
              "position": 0
            }
          ]
        },
        {
          "name": "setpublic",
          "trigger": "setpublic",
          "helpText": "Sets a teleport to be public, allowing other players to teleport to it.",
          "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",
          "arguments": [
            {
              "name": "tp",
              "type": "string",
              "helpText": "The location name.",
              "position": 0
            }
          ]
        },
        {
          "name": "setprivate",
          "trigger": "setprivate",
          "helpText": "Sets a teleport to be private, only the teleport owner can teleport to it.",
          "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",
          "arguments": [
            {
              "name": "tp",
              "type": "string",
              "helpText": "The location name.",
              "position": 0
            }
          ]
        },
        {
          "name": "setwaypoint",
          "trigger": "setwaypoint",
          "helpText": "Creates a new waypoint.",
          "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",
          "arguments": [
            {
              "name": "waypoint",
              "type": "string",
              "helpText": "The location name.",
              "position": 0
            }
          ]
        },
        {
          "name": "deletewaypoint",
          "trigger": "deletewaypoint",
          "helpText": "Deletes a waypoint.",
          "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",
          "arguments": [
            {
              "name": "waypoint",
              "type": "string",
              "helpText": "The location name.",
              "position": 0
            }
          ]
        },
        {
          "name": "listwaypoints",
          "trigger": "waypoints",
          "helpText": "Lists all waypoints.",
          "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",
          "arguments": []
        },
        {
          "name": "teleportwaypoint",
          "trigger": "teleportwaypoint",
          "helpText": "Placeholder command, this will not be used directly. The module will install aliases for this command corresponding to the waypoint names.",
          "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",
          "arguments": []
        }
      ],
      "hooks": [],
      "cronJobs": [
        {
          "name": "Waypoint reconciler",
          "temporalValue": "*/30 * * * *",
          "description": "",
          "function": "import { waypointReconciler } from './utils.js';\nasync function main() {\n    await waypointReconciler();\n}\nawait main();\n//# sourceMappingURL=Waypoint%20reconciler.js.map"
        }
      ],
      "functions": [
        {
          "name": "utils",
          "description": "",
          "function": "import { takaro, data } from '@takaro/helpers';\nexport function getVariableKey(tpName, pub = false) {\n    if (pub && tpName) {\n        return `pubtp_${tpName}`;\n    }\n    if (pub && !tpName) {\n        return 'pubtp_';\n    }\n    if (tpName) {\n        return `tp_${tpName}`;\n    }\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    }\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        }\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"
        }
      ],
      "permissions": [
        {
          "permission": "TELEPORTS_CREATE_PUBLIC",
          "friendlyName": "Create Public Teleports",
          "description": "Allows the player to create public teleports.",
          "canHaveCount": true
        },
        {
          "permission": "TELEPORTS_USE",
          "friendlyName": "Use Teleports",
          "description": "Allows the player to use teleports modules.",
          "canHaveCount": true
        },
        {
          "permission": "TELEPORTS_MANAGE_WAYPOINTS",
          "friendlyName": "Manage waypoints",
          "description": "Allows creating, deleting, and managing waypoints.",
          "canHaveCount": false
        }
      ]
    }
  ]
}