omegga 1.3.0 → 1.4.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 (121) hide show
  1. package/.claude/settings.local.json +17 -0
  2. package/README.md +39 -10
  3. package/bin/omegga +1 -1
  4. package/dist/brickadia/server.js +4 -8
  5. package/dist/brickadia/server.js.map +1 -1
  6. package/dist/index.js +6 -6
  7. package/dist/main.js +8 -7
  8. package/dist/main.js.map +1 -1
  9. package/dist/omegga/player.js +59 -25
  10. package/dist/omegga/player.js.map +1 -1
  11. package/dist/omegga/plugin/plugin_jsonrpc_stdio.js +54 -0
  12. package/dist/omegga/plugin/plugin_jsonrpc_stdio.js.map +1 -1
  13. package/dist/omegga/plugin/plugin_node_unsafe.js +6 -0
  14. package/dist/omegga/plugin/plugin_node_unsafe.js.map +1 -1
  15. package/dist/omegga/server.js +35 -1
  16. package/dist/omegga/server.js.map +1 -1
  17. package/dist/omegga/wrapper.js +1 -0
  18. package/dist/omegga/wrapper.js.map +1 -1
  19. package/dist/plugin.js +1 -2
  20. package/dist/plugin.js.map +1 -1
  21. package/dist/softconfig.js +33 -15
  22. package/dist/softconfig.js.map +1 -1
  23. package/dist/updater/steam.js +65 -12
  24. package/dist/updater/steam.js.map +1 -1
  25. package/dist/util/brick/checkBounds.js +1 -2
  26. package/dist/util/brick/checkBounds.js.map +1 -1
  27. package/dist/util/brick/displayName.js +1 -2
  28. package/dist/util/brick/displayName.js.map +1 -1
  29. package/dist/util/brick/getBounds.js +1 -2
  30. package/dist/util/brick/getBounds.js.map +1 -1
  31. package/dist/util/brick/getBrickSize.js +1 -2
  32. package/dist/util/brick/getBrickSize.js.map +1 -1
  33. package/dist/util/brick/getScaleAxis.js +1 -2
  34. package/dist/util/brick/getScaleAxis.js.map +1 -1
  35. package/dist/util/brick/setOwnership.js +1 -2
  36. package/dist/util/brick/setOwnership.js.map +1 -1
  37. package/dist/webserver/backend/api.js +2 -1
  38. package/dist/webserver/backend/api.js.map +1 -1
  39. package/dist/webserver/backend/database.js +3 -1
  40. package/dist/webserver/backend/database.js.map +1 -1
  41. package/package.json +3 -2
  42. package/public/app.html +18 -18
  43. package/public/assets/IconArrowRight-BuVxhqKX.js +2 -0
  44. package/public/assets/{IconArrowRight-CA5_cccJ.js.map → IconArrowRight-BuVxhqKX.js.map} +1 -1
  45. package/public/assets/IconCheck-DOe3u7iH.js +2 -0
  46. package/public/assets/{IconCheck-Dyq5qyY1.js.map → IconCheck-DOe3u7iH.js.map} +1 -1
  47. package/public/assets/IconLockOpen-Bs7Tsf6u.js +2 -0
  48. package/public/assets/{IconLockOpen-D95XLORK.js.map → IconLockOpen-Bs7Tsf6u.js.map} +1 -1
  49. package/public/assets/IconWorld-B6GK5qpx.js +2 -0
  50. package/public/assets/{IconWorld-DtARpBKX.js.map → IconWorld-B6GK5qpx.js.map} +1 -1
  51. package/public/assets/IconWorldPlus-DpfueG8_.js +2 -0
  52. package/public/assets/{IconWorldPlus-CGBAsLNj.js.map → IconWorldPlus-DpfueG8_.js.map} +1 -1
  53. package/public/assets/IconX-CvmO0bbE.js +2 -0
  54. package/public/assets/{IconX-SYtbnYKI.js.map → IconX-CvmO0bbE.js.map} +1 -1
  55. package/public/assets/app-S3WcjD4u.js +6 -0
  56. package/public/assets/{app-BtOlgo__.js.map → app-S3WcjD4u.js.map} +1 -1
  57. package/public/assets/{auth-CvxEWAMc.js → auth-6N37o421.js} +2 -2
  58. package/public/assets/{auth-CvxEWAMc.js.map → auth-6N37o421.js.map} +1 -1
  59. package/public/assets/client-BT1QYH0O.js +10 -0
  60. package/public/assets/{client-C5T7_OK9.js.map → client-BT1QYH0O.js.map} +1 -1
  61. package/public/assets/index-2cgXLhrt.js +2 -0
  62. package/public/assets/{index-CRRRLlCc.js.map → index-2cgXLhrt.js.map} +1 -1
  63. package/public/assets/{index-i4mjW0og.js → index-CrN8I5Az.js} +2 -2
  64. package/public/assets/index-CrN8I5Az.js.map +1 -0
  65. package/public/assets/index-CtCtK5BX.js +2 -0
  66. package/public/assets/{index-DqHVrEeL.js.map → index-CtCtK5BX.js.map} +1 -1
  67. package/public/assets/index-Cz1Unv84.js +10 -0
  68. package/public/assets/{index-Bq9C9SqB.js.map → index-Cz1Unv84.js.map} +1 -1
  69. package/public/assets/index-D0OPOe3j.js +2 -0
  70. package/public/assets/{index-c0qeY2gs.js.map → index-D0OPOe3j.js.map} +1 -1
  71. package/public/assets/{index-DYcAgWjJ.js → index-DY750sgZ.js} +2 -2
  72. package/public/assets/{index-DYcAgWjJ.js.map → index-DY750sgZ.js.map} +1 -1
  73. package/public/assets/jsx-runtime-BX5r4UiA.js +2 -0
  74. package/public/assets/jsx-runtime-BX5r4UiA.js.map +1 -0
  75. package/public/assets/jsx-runtime-DldvXD6N.js +2 -0
  76. package/public/assets/{jsx-runtime-Bw5QeaCk.js.map → jsx-runtime-DldvXD6N.js.map} +1 -1
  77. package/public/assets/shared/@components-Bt_lv7Wa.js +2 -0
  78. package/public/assets/shared/@components-Bt_lv7Wa.js.map +1 -0
  79. package/public/assets/shared/{@hooks-DfTzYBIL.js → @hooks-Ch_hJYh0.js} +2 -2
  80. package/public/assets/shared/{@hooks-DfTzYBIL.js.map → @hooks-Ch_hJYh0.js.map} +1 -1
  81. package/public/assets/shared/{@nanostores_react-HTG3s0lp.js → @nanostores_react-DJPF1Eqx.js} +2 -2
  82. package/public/assets/shared/{@nanostores_react-HTG3s0lp.js.map → @nanostores_react-DJPF1Eqx.js.map} +1 -1
  83. package/public/assets/shared/@tabler_icons-react-B4bN8gHc.js +3 -0
  84. package/public/assets/shared/{@tabler_icons-react--FJWdUou.js.map → @tabler_icons-react-B4bN8gHc.js.map} +1 -1
  85. package/public/assets/shared/nanostores-BFqqIY_c.js.map +1 -1
  86. package/public/assets/shared/react-dom-8Rcmh_FG.js +2 -0
  87. package/public/assets/shared/{react-dom-BznoGTRX.js.map → react-dom-8Rcmh_FG.js.map} +1 -1
  88. package/public/assets/shared/react-iXLZ_Bod.js +2 -0
  89. package/public/assets/shared/{react-CR6vSpIu.js.map → react-iXLZ_Bod.js.map} +1 -1
  90. package/public/assets/shared/react_jsx-runtime-BwhiLcBy.js +2 -0
  91. package/public/assets/shared/{react_jsx-runtime-C15Zu6_p.js.map → react_jsx-runtime-BwhiLcBy.js.map} +1 -1
  92. package/public/assets/shared/{wouter-DbmGxXTo.js → wouter-CUC1caxu.js} +2 -2
  93. package/public/assets/shared/wouter-CUC1caxu.js.map +1 -0
  94. package/public/auth.html +14 -14
  95. package/templates/safe-ts/omegga.d.ts +30 -0
  96. package/public/assets/IconArrowRight-CA5_cccJ.js +0 -7
  97. package/public/assets/IconCheck-Dyq5qyY1.js +0 -17
  98. package/public/assets/IconLockOpen-D95XLORK.js +0 -7
  99. package/public/assets/IconWorld-DtARpBKX.js +0 -72
  100. package/public/assets/IconWorldPlus-CGBAsLNj.js +0 -182
  101. package/public/assets/IconX-SYtbnYKI.js +0 -12
  102. package/public/assets/app-BtOlgo__.js +0 -6
  103. package/public/assets/client-C5T7_OK9.js +0 -26
  104. package/public/assets/index-Bq9C9SqB.js +0 -10
  105. package/public/assets/index-CRRRLlCc.js +0 -10
  106. package/public/assets/index-DqHVrEeL.js +0 -10
  107. package/public/assets/index-c0qeY2gs.js +0 -10
  108. package/public/assets/index-i4mjW0og.js.map +0 -1
  109. package/public/assets/jsx-runtime-Bw5QeaCk.js +0 -10
  110. package/public/assets/jsx-runtime-DoEZbXM1.js +0 -2
  111. package/public/assets/jsx-runtime-DoEZbXM1.js.map +0 -1
  112. package/public/assets/shared/@components-DVehBp7v.js +0 -2
  113. package/public/assets/shared/@components-DVehBp7v.js.map +0 -1
  114. package/public/assets/shared/@tabler_icons-react--FJWdUou.js +0 -29458
  115. package/public/assets/shared/react-CR6vSpIu.js +0 -2
  116. package/public/assets/shared/react-dom-BznoGTRX.js +0 -2
  117. package/public/assets/shared/react_jsx-runtime-C15Zu6_p.js +0 -2
  118. package/public/assets/shared/wouter-DbmGxXTo.js.map +0 -1
  119. package/vite.backend.config.mts +0 -46
  120. package/vite.frontend.config.mts +0 -58
  121. package/vitest.backend.config.mts +0 -7
@@ -1 +1 @@
1
- {"version":3,"file":"player.js","sources":["../../src/omegga/player.ts"],"sourcesContent":["import type { OmeggaLike, OmeggaPlayer, WeaponClass } from '@/plugin';\nimport { IBrickBounds } from '@util/brick';\nimport { WriteSaveObject } from 'brs-js';\nimport { brick as brickUtils, color } from '../util/';\n\nconst DEFAULT_PERMS: Record<string, string[]> = {\n moderator: [\n 'Bricks.ClearAll',\n 'Minigame.AlwaysLeave',\n 'Players.Kick',\n 'Players.TPInMinigame',\n 'Players.TPOthers',\n 'Self.Ghost',\n ],\n admin: [\n 'Bricks.ClearAll',\n 'Bricks.ClearOwn',\n 'Bricks.IgnoreTrust',\n 'Bricks.Load',\n 'Map.Environment',\n 'Minigame.AlwaysEdit',\n 'Minigame.AlwaysLeave',\n 'Minigame.AlwaysSwitchTeam',\n 'Minigame.MakeDefault',\n 'Minigame.MakePersistent',\n 'Minigame.UseAllBricks',\n 'Players.Ban',\n 'Players.Kick',\n 'Players.TPInMinigame',\n 'Players.TPOthers',\n 'Roles.Grant',\n 'Self.Ghost',\n 'Server.ChangeRoles',\n 'Server.ChangeSettings',\n 'Server.FreezeCamera',\n 'Tools.Selector.BypassLimits',\n 'Tools.Selector.BypassTimeouts',\n ],\n};\n\nclass Player implements OmeggaPlayer {\n #omegga: OmeggaLike;\n name: string;\n displayName: string;\n id: string;\n controller: string;\n state: string;\n\n static getRoles(omegga: OmeggaLike, id: string): readonly string[] {\n const data = omegga.getRoleAssignments().savedPlayerRoles[id];\n return Object.freeze(data && data.roles ? data.roles : []);\n }\n\n static getPermissions(\n omegga: OmeggaLike,\n id: string,\n ): Record<string, boolean> {\n const { roles, defaultRole } = omegga.getRoleSetup();\n\n // if the player is the host, the player has every permission\n if (omegga.host.id === id) {\n return Object.freeze(\n Object.fromEntries(\n [].concat(\n defaultRole.permissions.map(p => [p.name, true]),\n // sometimes the default role does not have every permission listed\n ...roles.map(r => r.permissions.map(p => [p.name, true])),\n ),\n ),\n );\n }\n\n // get the player's roles\n const playerRoles = Player.getRoles(omegga, id).map(r => r.toLowerCase());\n\n // default player permissions\n const permissions: Record<string, boolean> = {\n 'Bricks.ClearAll': false,\n 'Bricks.ClearOwn': true,\n 'Bricks.Delete': true,\n 'Bricks.Edit': true,\n 'Bricks.IgnoreTrust': false,\n 'Bricks.Paint': true,\n 'Bricks.Place': true,\n 'BricksItems.Spawn': true,\n 'Map.Change': false,\n 'Map.Environment': false,\n 'Map.SetSpawn': false,\n 'Minigame.AlwaysEdit': false,\n 'Minigame.AlwaysLeave': false,\n 'Minigame.AlwaysSwitchTeam': false,\n 'Minigame.Create': true,\n 'Minigame.MakePersistent': false,\n 'Minigame.UseAllBricks': false,\n 'Players.Ban': false,\n 'Players.TPInMinigame': false,\n 'Players.TPOthers': false,\n 'Players.TPSelf': true,\n 'Roles.Grant': false,\n 'Self.Flashlight': true,\n 'Self.Fly': true,\n 'Self.FreezeCamera': false,\n 'Self.Ghost': false,\n 'Self.Sprint': true,\n 'Self.Suicide': true,\n 'Tools.Selector.Use': true,\n };\n\n // apply all permissions from default role\n for (const p of defaultRole.permissions) {\n // technically this can never be Unchanged so it's always on enabled or allowed\n permissions[p.name] =\n p.state === 'Unchanged' ? permissions[p.name] : p.state === 'Allowed';\n }\n\n // loop through all the roles\n for (const role of roles) {\n // ignore ones the player does not have\n if (!playerRoles.includes(role.name.toLowerCase())) continue;\n\n const defaultPerms = DEFAULT_PERMS[role.name.toLowerCase()] || [];\n // iterate through default permissions\n for (const perm of defaultPerms) {\n // if they are not overriden, set it to true\n if (!role.permissions.find(r => r.name === perm))\n permissions[perm] = true;\n }\n\n // add all the new permissions the player now has\n for (const p of role.permissions) {\n // permission is disabled on forbidden, persisted on unchanged, and enabled on bEnabled or Allowed\n permissions[p.name] =\n p.state !== 'Forbidden' &&\n (p.state === 'Unchanged'\n ? permissions[p.name]\n : permissions[p.name] || p.state === 'Allowed');\n permissions[p.name] = permissions[p.name];\n }\n }\n\n return Object.freeze(permissions);\n }\n\n static kill(omegga: OmeggaLike, target: string | OmeggaPlayer) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (target?.name) omegga.writeln(`Server.Players.Kill \"${target?.name}\"`);\n }\n\n static damage(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n amount: number,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (amount === 0) return;\n if (target?.name)\n omegga.writeln(`Server.Players.Damage \"${target?.name}\" ${amount}`);\n }\n\n static heal(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n amount: number,\n ) {\n if (amount === 0) return;\n Player.damage(omegga, target, -amount);\n }\n\n static giveItem(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n item: WeaponClass,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (!item) return;\n if (target?.name)\n omegga.writeln(`Server.Players.GiveItem \"${target?.name}\" ${item}`);\n }\n\n static takeItem(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n item: WeaponClass,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (!item) return;\n if (target?.name)\n omegga.writeln(`Server.Players.RemoveItem \"${target?.name}\" ${item}`);\n }\n\n static setTeam(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n teamIndex: number,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (target?.name)\n omegga.writeln(`Server.Players.SetTeam \"${target?.name}\" ${teamIndex}`);\n }\n\n static setMinigame(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n index: number,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (target?.name)\n omegga.writeln(`Server.Players.SetMinigame \"${target?.name}\" ${index}`);\n }\n\n static setScore(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n minigameIndex: number,\n score: number,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (target?.name)\n omegga.writeln(\n `Server.Players.SetLeaderboardValue \"${target?.name}\" ${minigameIndex} ${score}`,\n );\n }\n\n static async getScore(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n minigameIndex: number,\n ): Promise<number> {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (target?.name) {\n const name = target?.name;\n const id = target?.id;\n\n const match = await omegga.addWatcher(\n (line, match) => {\n if (match && match.groups.generator === 'LogConsoleCommands') {\n const test = match.groups.data.match(\n /^(?<uuid>.+) leaderboard value (?<minigame>\\d+) = (?<score>-?\\d+)$/,\n );\n if (!test) return;\n if (test.groups.uuid !== id) return;\n if (Number(test.groups.minigame) !== minigameIndex) return;\n return test;\n }\n },\n {\n timeoutDelay: 1000,\n exec: () =>\n omegga.writeln(\n `Server.Players.PrintLeaderboardValue \"${name}\" ${minigameIndex}`,\n ),\n },\n );\n if (match) return Number(match[0].groups.score);\n }\n return 0;\n }\n\n /**\n * players are not to be constructed\n * @constructor\n * @param omegga Omegga Instance\n * @param name Player Name\n * @param displayName Player Display Name\n * @param id Player Id\n * @param controller Player Controller\n * @param state Player State\n */\n constructor(\n omegga: OmeggaLike,\n username: string,\n displayName: string,\n id: string,\n controller: string,\n state: string,\n ) {\n this.#omegga = omegga;\n this.name = username;\n this.displayName = displayName;\n this.id = id;\n this.controller = controller;\n this.state = state;\n }\n\n getOmegga(): OmeggaLike {\n return this.#omegga;\n }\n\n clone(): OmeggaPlayer {\n return new Player(\n this.#omegga,\n this.name,\n this.displayName,\n this.id,\n this.controller,\n this.state,\n );\n }\n\n raw(): [string, string, string, string, string] {\n return [this.name, this.displayName, this.id, this.controller, this.state];\n }\n\n isHost(): boolean {\n return this.#omegga.host.id === this.id;\n }\n\n clearBricks(quiet = false) {\n this.#omegga.clearBricks(this.id, quiet);\n }\n\n getRoles(): readonly string[] {\n return Player.getRoles(this.#omegga, this.id);\n }\n\n getPermissions(): Record<string, boolean> {\n return Player.getPermissions(this.#omegga, this.id);\n }\n\n getNameColor(): string {\n const { roles, defaultRole, ownerRoleColor, bOwnerRoleHasColor } =\n this.#omegga.getRoleSetup();\n\n // host check if host has host color\n if (this.isHost() && bOwnerRoleHasColor)\n return color.rgbToHex(ownerRoleColor);\n\n // get the player's role\n const playerRoles = this.getRoles().map(r => r.toLowerCase());\n\n // only if the player actually has roles...\n if (playerRoles.length > 0) {\n // check the role list in reverse for the player's role (highest tier first)\n const found = roles\n .slice()\n .reverse()\n .find(\n role =>\n role.bHasColor && playerRoles.includes(role.name.toLowerCase()),\n );\n\n if (found) return color.rgbToHex(found.color);\n }\n\n return color.rgbToHex(\n defaultRole.bHasColor\n ? defaultRole.color\n : { r: 255, g: 255, b: 255, a: 255 },\n );\n }\n\n async getPawn(): Promise<string | null> {\n // given a player controller, match the player's pawn\n const pawnRegExp = new RegExp(\n `^(?<index>\\\\d+)\\\\) BP_PlayerController_C .+?PersistentLevel\\\\.${this.controller}\\\\.Pawn = .*?(?:BP_FigureV2_C'.+:PersistentLevel\\\\.)?(?<pawn>BP_FigureV2_C_\\\\d+|None)'?`,\n );\n\n // wait for the pawn watcher to return a pawn\n const [{ groups: { pawn = null } = {} } = {}] =\n await this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BP_PlayerController_C Pawn Name=' + this.controller,\n pawnRegExp,\n { first: 'index', timeoutDelay: 500 },\n );\n\n if (pawn === 'None') return null;\n\n return pawn;\n }\n\n async getPosition(): Promise<[number, number, number] | null> {\n // this is here because my text editor had weird syntax highlighting glitches when the other omeggas were replaced with this.#omegga...\n // guess the code is \"too new\" :egg:\n const omegga = this.#omegga;\n\n // given a player controller, match the player's pawn\n const pawnRegExp = new RegExp(\n `^(?<index>\\\\d+)\\\\) BP_PlayerController_C .+?PersistentLevel\\\\.${this.controller}\\\\.Pawn = .*?(?:BP_FigureV2_C'.+:PersistentLevel\\\\.)?(?<pawn>BP_FigureV2_C_\\\\d+|None)'?`,\n );\n\n // wait for the pawn watcher to return a pawn\n const [\n {\n groups: { pawn },\n },\n ] = await omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BP_PlayerController_C Pawn Name=' + this.controller,\n pawnRegExp,\n { first: 'index', timeoutDelay: 100 },\n );\n\n if (pawn === 'None') return null;\n\n // given a player's pawn, match the player's position\n const posRegExp = new RegExp(\n `CapsuleComponent .+?PersistentLevel\\\\.${pawn}\\\\.CollisionCylinder\\\\.RelativeLocation = \\\\(X=(?<x>[\\\\d\\\\.-]+),Y=(?<y>[\\\\d\\\\.-]+),Z=(?<z>[\\\\d\\\\.-]+)\\\\)`,\n );\n\n // wait for the position promise\n const [\n {\n groups: { x, y, z },\n },\n ] = await omegga.addWatcher(posRegExp, {\n // request the position for this player's pawn\n exec: () =>\n omegga.writeln(\n `GetAll SceneComponent RelativeLocation Name=CollisionCylinder Outer=${pawn}`,\n ),\n timeoutDelay: 100,\n });\n\n // return the player's position as an array of numbers\n return [Number(x), Number(y), Number(z)];\n }\n\n async getGhostBrick(): Promise<{\n targetGrid: string;\n location: number[];\n orientation: string;\n }> {\n const { controller } = this;\n\n const previewClass = 'BP_ToolPreviewActor_C';\n\n const ownerRegExp = new RegExp(\n `^(?<index>\\\\d+)\\\\) ${previewClass} (.+):PersistentLevel\\\\.(?<actor>${previewClass}_\\\\d+)\\.Owner = .*?BP_PlayerController_C'(.+):PersistentLevel\\\\.(?<controller>BP_PlayerController_C_\\\\d+)'$`,\n );\n const transformParamsRegExp = new RegExp(\n `^(?<index>\\\\d+)\\\\) ${previewClass} (.+):PersistentLevel\\\\.(?<actor>${previewClass}_\\\\d+)\\\\.TransformParameters = \\\\(TargetGrid=(\"(?<targetGrid>.+)\"|None),Location=\\\\(X=(?<x>.+),Y=(?<y>.+),Z=(?<z>.+)\\\\),Orientation=(?<orientation>.+)\\\\)$`,\n );\n\n const [owners, transformParams] = await Promise.all([\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n `GetAll ${previewClass} Owner`,\n ownerRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n `GetAll ${previewClass} TransformParameters`,\n transformParamsRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n ]);\n\n // get BrickGridPreviewActor by controller\n const owner = owners.find(owner => owner.groups.controller === controller);\n\n if (!owner) return;\n\n const actor = owner.groups.actor;\n // get transform parameters for the found actor\n const transformParameters = transformParams.find(\n transformParameters => transformParameters.groups.actor === actor,\n );\n\n if (!transformParameters) return;\n\n return {\n targetGrid: transformParameters.groups.targetGrid,\n location: [\n +transformParameters.groups.x,\n +transformParameters.groups.y,\n +transformParameters.groups.z,\n ],\n orientation: transformParameters.groups.orientation,\n };\n }\n\n async getPaint(): Promise<{\n materialIndex: string;\n materialAlpha: string;\n material: string;\n color: number[];\n }> {\n const { controller } = this;\n\n const match = await this.#omegga\n .addWatcher<{\n materialIndex: string;\n materialAlpha: string;\n material: string;\n color: number[];\n }>(\n line => {\n // [date][counter]0) BP_PlayerState_C /Game/Maps/Plate/Plate.Plate:PersistentLevel.BP_PlayerState_C_2147482378.ColorSelectionState = (SelectedColor=(B=6,G=73,R=246,A=255),MaterialIndex=3,MaterialAlpha=5)\n const match = line.match(\n /^\\[[^\\]]+\\]\\[[^\\]]+\\]\\d+\\) BP_PlayerState_C .+?PersistentLevel\\.(?<state>BP_PlayerState_C_\\d+)\\.ColorSelectionState = \\(SelectedColor=\\(B=(?<b>\\d+),G=(?<g>\\d+),R=(?<r>\\d+),A=(?<a>\\d+)\\),MaterialIndex=(?<materialIndex>\\d+),MaterialAlpha=(?<materialAlpha>\\d+)\\)$/,\n );\n if (!match) return;\n if (match.groups.state !== this.state) return;\n const colorRaw = [+match.groups.r, +match.groups.g, +match.groups.b];\n return {\n materialIndex: match.groups.materialIndex,\n materialAlpha: match.groups.materialAlpha,\n material:\n brickUtils.BRICK_CONSTANTS.DEFAULT_MATERIALS[\n Number(match.groups.materialIndex)\n ],\n color: colorRaw,\n };\n },\n {\n timeoutDelay: 1000,\n exec: () =>\n this.#omegga.writeln('GetAll BRPlayerState ColorSelectionState'),\n },\n )\n .catch(() => null);\n if (!match?.[0]) return;\n return match[0];\n }\n\n async isCrouched(pawn?: string): Promise<boolean> {\n if (!pawn) pawn = await this.getPawn();\n\n const reg =\n /(?<index>\\d+)\\) BP_FigureV2_C .+?PersistentLevel\\.(?<pawn>BP_FigureV2_C_\\d+)\\.bIsCrouched = (?<crouched>True|False)$/;\n\n const resp = await this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BP_FigureV2_C bIsCrouched Name=' + pawn,\n reg,\n { first: 'index', timeoutDelay: 500 },\n );\n\n const me = resp.find(r => r.groups.pawn === pawn);\n if (!me) return false;\n\n return me.groups.crouched == 'True';\n }\n\n async isDead(pawn?: string): Promise<boolean> {\n if (!pawn) pawn = await this.getPawn();\n\n const reg =\n /(?<index>\\d+)\\) BP_FigureV2_C .+?PersistentLevel\\.(?<pawn>BP_FigureV2_C_\\d+)\\.bIsDead = (?<dead>True|False)$/;\n\n const resp = await this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BP_FigureV2_C bIsDead Name=' + pawn,\n reg,\n { first: 'index', timeoutDelay: 500 },\n );\n\n const me = resp.find(r => r.groups.pawn === pawn);\n if (!me) return true;\n\n return me.groups.dead == 'True';\n }\n\n async getTemplateBounds() {\n const { controller } = this;\n\n const brickTemplateRegExp =\n /^(?<index>\\d+)\\) Tool_Selector_C (.+):PersistentLevel\\.(?<tool>Tool_Selector_C_\\d+)\\.CurrentTemplate = (.+)Brickadia.BrickBuildingTemplate'(.+)Transient.(?<templateName>BrickBuildingTemplate_\\d+)'$/;\n const brickTemplateOwnerRegExp =\n /^(?<index>\\d+)\\) Tool_Selector_C (.+):PersistentLevel\\.(?<tool>Tool_Selector_C_\\d+)\\.Owner = (.+)(?<controller>BP_PlayerController_C_\\d+)'$/;\n const minBoundsRegExp =\n /^(?<index>\\d+)\\) BrickBuildingTemplate (.+)Transient\\.(?<templateName>BrickBuildingTemplate_\\d+)\\.MinBounds = \\(X=(?<x>.+),Y=(?<y>.+),Z=(?<z>.+)\\)$/;\n const maxBoundsRegExp =\n /^(?<index>\\d+)\\) BrickBuildingTemplate (.+)Transient\\.(?<templateName>BrickBuildingTemplate_\\d+)\\.MaxBounds = \\(X=(?<x>.+),Y=(?<y>.+),Z=(?<z>.+)\\)$/;\n const centerRegExp =\n /^(?<index>\\d+)\\) BrickBuildingTemplate (.+)Transient\\.(?<templateName>BrickBuildingTemplate_\\d+)\\.Center = \\(X=(?<x>.+),Y=(?<y>.+),Z=(?<z>.+)\\)$/;\n\n const [templates, owners, minBounds, maxBounds, centers] =\n await Promise.all([\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll Tool_Selector_C CurrentTemplate',\n brickTemplateRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll Tool_Selector_C Owner',\n brickTemplateOwnerRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BrickBuildingTemplate MinBounds',\n minBoundsRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BrickBuildingTemplate MaxBounds',\n maxBoundsRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BrickBuildingTemplate Center',\n centerRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n ]);\n\n if (\n !templates.length ||\n !owners.length ||\n !minBounds.length ||\n !maxBounds.length ||\n !centers.length\n )\n return;\n\n // get selector for this controller, we need to handle if there are multiple selectors for the same controller\n const selectors = owners\n .filter(selectors => selectors.groups.controller === controller)\n .map(selectors => selectors.groups.tool)\n .sort();\n const selector = selectors[0]; // grab the most recently created\n\n if (!selector) {\n return;\n }\n\n // template for this selector, we need to handle if there are multiple templates for the same selector and grab the most recent one\n const brickTemplates = templates\n .filter(template => template.groups.tool === selector)\n .map(template => template.groups.templateName)\n .sort();\n const templateName = brickTemplates[0]; // grab the most recently created\n\n if (!templateName) {\n return;\n }\n\n // find all values with matching template name\n const minBound = minBounds.find(\n minBound => minBound.groups.templateName === templateName,\n );\n const maxBound = maxBounds.find(\n maxBound => maxBound.groups.templateName === templateName,\n );\n const center = centers.find(\n center => center.groups.templateName === templateName,\n );\n\n if (!minBound || !maxBound || !center) return;\n\n return {\n minBound: [+minBound.groups.x, +minBound.groups.y, +minBound.groups.z],\n maxBound: [+maxBound.groups.x, +maxBound.groups.y, +maxBound.groups.z],\n center: [+center.groups.x, +center.groups.y, +center.groups.z],\n } as IBrickBounds;\n }\n\n async getTemplateBoundsData() {\n const templateBounds = await this.getTemplateBounds();\n\n if (!templateBounds) return;\n\n const saveData = await this.#omegga.getSaveData({\n center: templateBounds.center,\n extent: [\n Math.round(\n (templateBounds.maxBound[0] - templateBounds.minBound[0]) / 2,\n ),\n Math.round(\n (templateBounds.maxBound[1] - templateBounds.minBound[1]) / 2,\n ),\n Math.round(\n (templateBounds.maxBound[2] - templateBounds.minBound[2]) / 2,\n ),\n ],\n });\n\n if (!saveData) return;\n\n // filter bricks outside the bounds\n // no longer necessary thanks to Bricks.SaveRegion\n /* saveData.bricks = (saveData.bricks as Brick[]).filter(brick => {\n return brickUtils.checkBounds(\n brick,\n saveData.brick_assets,\n templateBounds\n );\n }) as typeof saveData.bricks; */\n\n if (saveData.bricks.length > 0) {\n return saveData;\n }\n\n return undefined;\n }\n\n loadBricks(saveName: string) {\n this.#omegga.loadBricksOnPlayer(saveName, this);\n }\n\n async loadSaveData(\n saveData: WriteSaveObject,\n { offX = 0, offY = 0, offZ = 0 } = {},\n ) {\n await this.#omegga.loadSaveDataOnPlayer(saveData, this, {\n offX,\n offY,\n offZ,\n });\n }\n\n async loadDataAtGhostBrick(\n saveData: WriteSaveObject,\n { rotate = true, offX = 0, offY = 0, offZ = 0, quiet = true } = {},\n ) {\n const ghostBrickData = await this.getGhostBrick();\n\n if (!ghostBrickData || !saveData) return;\n\n // get bounds of the bricks\n const bounds = brickUtils.getBounds(saveData);\n\n if (rotate) {\n const orientation =\n brickUtils.BRICK_CONSTANTS.orientationMap[ghostBrickData.orientation];\n saveData.bricks = saveData.bricks.map(brick =>\n brickUtils.rotate(brick, orientation),\n );\n // rotate bounds, if we dont use the original bounds they are off by 1 sometimes >:(\n bounds.minBound = brickUtils.BRICK_CONSTANTS.translationTable[\n brickUtils.d2o(...orientation)\n ](bounds.minBound);\n bounds.maxBound = brickUtils.BRICK_CONSTANTS.translationTable[\n brickUtils.d2o(...orientation)\n ](bounds.maxBound);\n bounds.center = brickUtils.BRICK_CONSTANTS.translationTable[\n brickUtils.d2o(...orientation)\n ](bounds.center);\n }\n\n // calculate offset from bricks center to ghost brick center\n const offset = bounds.center.map(\n (center, index) => ghostBrickData.location[index] - center,\n );\n\n // load at offset location\n await this.#omegga.loadSaveData(saveData, {\n offX: offX + offset[0],\n offY: offY + offset[1],\n offZ: offZ + offset[2],\n quiet,\n });\n }\n\n kill() {\n Player.kill(this.#omegga, this);\n }\n\n damage(amount: number): void {\n Player.damage(this.#omegga, this, amount);\n }\n\n heal(amount: number): void {\n Player.heal(this.#omegga, this, amount);\n }\n\n giveItem(item: WeaponClass): void {\n Player.giveItem(this.#omegga, this, item);\n }\n\n takeItem(item: WeaponClass): void {\n Player.takeItem(this.#omegga, this, item);\n }\n\n setTeam(teamIndex: number): void {\n Player.setTeam(this.#omegga, this, teamIndex);\n }\n\n setMinigame(index: number): void {\n Player.setMinigame(this.#omegga, this, index);\n }\n\n setScore(minigameIndex: number, score: number): void {\n Player.setScore(this.#omegga, this, minigameIndex, score);\n }\n\n getScore(minigameIndex: number): Promise<number> {\n return Player.getScore(this.#omegga, this, minigameIndex);\n }\n}\n\nglobal.Player = Player;\n\nexport default Player;\n"],"names":["index","match","color","owner","transformParameters","brickUtils","selectors","minBound","maxBound","center"],"mappings":"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"}
1
+ {"version":3,"file":"player.js","sources":["../../src/omegga/player.ts"],"sourcesContent":["import type { OmeggaLike, OmeggaPlayer, WeaponClass } from '@/plugin';\nimport { IBrickBounds } from '@util/brick';\nimport { WriteSaveObject } from 'brs-js';\nimport { brick as brickUtils, color } from '../util/';\n\nconst DEFAULT_PERMS: Record<string, string[]> = {\n moderator: [\n 'Bricks.ClearAll',\n 'Minigame.AlwaysLeave',\n 'Players.Kick',\n 'Players.TPInMinigame',\n 'Players.TPOthers',\n 'Self.Ghost',\n ],\n admin: [\n 'Bricks.ClearAll',\n 'Bricks.ClearOwn',\n 'Bricks.IgnoreTrust',\n 'Bricks.Load',\n 'Map.Environment',\n 'Minigame.AlwaysEdit',\n 'Minigame.AlwaysLeave',\n 'Minigame.AlwaysSwitchTeam',\n 'Minigame.MakeDefault',\n 'Minigame.MakePersistent',\n 'Minigame.UseAllBricks',\n 'Players.Ban',\n 'Players.Kick',\n 'Players.TPInMinigame',\n 'Players.TPOthers',\n 'Roles.Grant',\n 'Self.Ghost',\n 'Server.ChangeRoles',\n 'Server.ChangeSettings',\n 'Server.FreezeCamera',\n 'Tools.Selector.BypassLimits',\n 'Tools.Selector.BypassTimeouts',\n ],\n};\n\nclass Player implements OmeggaPlayer {\n #omegga: OmeggaLike;\n name: string;\n displayName: string;\n id: string;\n controller: string;\n state: string;\n\n static getRoles(omegga: OmeggaLike, id: string): readonly string[] {\n const data = omegga.getRoleAssignments().savedPlayerRoles[id];\n return Object.freeze(data && data.roles ? data.roles : []);\n }\n\n static getPermissions(\n omegga: OmeggaLike,\n id: string,\n ): Record<string, boolean> {\n const { roles, defaultRole } = omegga.getRoleSetup();\n\n // if the player is the host, the player has every permission\n if (omegga.host.id === id) {\n return Object.freeze(\n Object.fromEntries(\n [].concat(\n defaultRole.permissions.map(p => [p.name, true]),\n // sometimes the default role does not have every permission listed\n ...roles.map(r => r.permissions.map(p => [p.name, true])),\n ),\n ),\n );\n }\n\n // get the player's roles\n const playerRoles = Player.getRoles(omegga, id).map(r => r.toLowerCase());\n\n // default player permissions\n const permissions: Record<string, boolean> = {\n 'Bricks.ClearAll': false,\n 'Bricks.ClearOwn': true,\n 'Bricks.Delete': true,\n 'Bricks.Edit': true,\n 'Bricks.IgnoreTrust': false,\n 'Bricks.Paint': true,\n 'Bricks.Place': true,\n 'BricksItems.Spawn': true,\n 'Map.Change': false,\n 'Map.Environment': false,\n 'Map.SetSpawn': false,\n 'Minigame.AlwaysEdit': false,\n 'Minigame.AlwaysLeave': false,\n 'Minigame.AlwaysSwitchTeam': false,\n 'Minigame.Create': true,\n 'Minigame.MakePersistent': false,\n 'Minigame.UseAllBricks': false,\n 'Players.Ban': false,\n 'Players.TPInMinigame': false,\n 'Players.TPOthers': false,\n 'Players.TPSelf': true,\n 'Roles.Grant': false,\n 'Self.Flashlight': true,\n 'Self.Fly': true,\n 'Self.FreezeCamera': false,\n 'Self.Ghost': false,\n 'Self.Sprint': true,\n 'Self.Suicide': true,\n 'Tools.Selector.Use': true,\n };\n\n // apply all permissions from default role\n for (const p of defaultRole.permissions) {\n // technically this can never be Unchanged so it's always on enabled or allowed\n permissions[p.name] =\n p.state === 'Unchanged' ? permissions[p.name] : p.state === 'Allowed';\n }\n\n // loop through all the roles\n for (const role of roles) {\n // ignore ones the player does not have\n if (!playerRoles.includes(role.name.toLowerCase())) continue;\n\n const defaultPerms = DEFAULT_PERMS[role.name.toLowerCase()] || [];\n // iterate through default permissions\n for (const perm of defaultPerms) {\n // if they are not overriden, set it to true\n if (!role.permissions.find(r => r.name === perm))\n permissions[perm] = true;\n }\n\n // add all the new permissions the player now has\n for (const p of role.permissions) {\n // permission is disabled on forbidden, persisted on unchanged, and enabled on bEnabled or Allowed\n permissions[p.name] =\n p.state !== 'Forbidden' &&\n (p.state === 'Unchanged'\n ? permissions[p.name]\n : permissions[p.name] || p.state === 'Allowed');\n permissions[p.name] = permissions[p.name];\n }\n }\n\n return Object.freeze(permissions);\n }\n\n static kill(omegga: OmeggaLike, target: string | OmeggaPlayer) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (target?.name) omegga.writeln(`Server.Players.Kill \"${target?.name}\"`);\n }\n\n static damage(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n amount: number,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (amount === 0) return;\n if (target?.name)\n omegga.writeln(`Server.Players.Damage \"${target?.name}\" ${amount}`);\n }\n\n static heal(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n amount: number,\n ) {\n if (amount === 0) return;\n Player.damage(omegga, target, -amount);\n }\n\n static giveItem(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n item: WeaponClass,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (!item) return;\n if (target?.name)\n omegga.writeln(`Server.Players.GiveItem \"${target?.name}\" ${item}`);\n }\n\n static takeItem(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n item: WeaponClass,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (!item) return;\n if (target?.name)\n omegga.writeln(`Server.Players.RemoveItem \"${target?.name}\" ${item}`);\n }\n\n static setTeam(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n teamIndex: number,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (target?.name)\n omegga.writeln(`Server.Players.SetTeam \"${target?.name}\" ${teamIndex}`);\n }\n\n static setMinigame(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n index: number,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (target?.name)\n omegga.writeln(`Server.Players.SetMinigame \"${target?.name}\" ${index}`);\n }\n\n static setScore(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n minigameIndex: number,\n score: number,\n ) {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (target?.name)\n omegga.writeln(\n `Server.Players.SetLeaderboardValue \"${target?.name}\" ${minigameIndex} ${score}`,\n );\n }\n\n static async getScore(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n minigameIndex: number,\n ): Promise<number> {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (!target?.name) return 0;\n\n const name = target?.name;\n const id = target?.id;\n\n const match = await omegga.addWatcher(\n (line, match) => {\n if (match?.groups.generator !== 'LogConsoleCommands') return;\n\n const test = match.groups.data.match(\n /^(?<uuid>.+) leaderboard value (?<minigame>\\d+) = (?<score>-?\\d+)$/,\n );\n if (!test) return;\n if (test.groups.uuid !== id) return;\n if (Number(test.groups.minigame) !== minigameIndex) return;\n return test;\n },\n {\n timeoutDelay: 1000,\n exec: () =>\n omegga.writeln(\n `Server.Players.PrintLeaderboardValue \"${name}\" ${minigameIndex}`,\n ),\n },\n );\n if (match) return Number(match[0].groups.score);\n }\n\n static setLeaderboard(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n key: string,\n value: number,\n ): void {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (!target?.name) return null;\n\n omegga.writeln(\n `Server.Players.SetLeaderboardValue \"${target.name}\" \"${key}\" \"${value}\"`,\n );\n }\n\n static async getLeaderboard(\n omegga: OmeggaLike,\n target: string | OmeggaPlayer,\n key: string,\n ): Promise<number | null> {\n if (typeof target === 'string') target = omegga.getPlayer(target);\n if (!target?.name) return null;\n\n // LogConsoleCommands: <uuid> leaderboard value Key = 0\n const match = await omegga\n .addWatcher<RegExpMatchArray>(\n (line, match) => {\n if (match?.groups.generator !== 'LogConsoleCommands') return;\n\n const test = match.groups.data.match(\n /^(?<uuid>.+) leaderboard value (?<key>.+) = (?<value>-?\\d+)$/,\n );\n if (!test) return;\n if (test.groups.uuid !== target.id) return;\n if (test.groups.key !== key) return;\n return test;\n },\n {\n timeoutDelay: 1000,\n exec: () =>\n omegga.writeln(\n `Server.Players.PrintLeaderboardValue \"${target.name}\" \"${key}\"`,\n ),\n },\n )\n .catch(() => null);\n if (match) return Number(match[0].groups.value);\n return null;\n }\n\n /**\n * players are not to be constructed\n * @constructor\n * @param omegga Omegga Instance\n * @param name Player Name\n * @param displayName Player Display Name\n * @param id Player Id\n * @param controller Player Controller\n * @param state Player State\n */\n constructor(\n omegga: OmeggaLike,\n username: string,\n displayName: string,\n id: string,\n controller: string,\n state: string,\n ) {\n this.#omegga = omegga;\n this.name = username;\n this.displayName = displayName;\n this.id = id;\n this.controller = controller;\n this.state = state;\n }\n\n getOmegga(): OmeggaLike {\n return this.#omegga;\n }\n\n clone(): OmeggaPlayer {\n return new Player(\n this.#omegga,\n this.name,\n this.displayName,\n this.id,\n this.controller,\n this.state,\n );\n }\n\n raw(): [string, string, string, string, string] {\n return [this.name, this.displayName, this.id, this.controller, this.state];\n }\n\n isHost(): boolean {\n return this.#omegga.host.id === this.id;\n }\n\n clearBricks(quiet = false) {\n this.#omegga.clearBricks(this.id, quiet);\n }\n\n getRoles(): readonly string[] {\n return Player.getRoles(this.#omegga, this.id);\n }\n\n getPermissions(): Record<string, boolean> {\n return Player.getPermissions(this.#omegga, this.id);\n }\n\n getNameColor(): string {\n const { roles, defaultRole, ownerRoleColor, bOwnerRoleHasColor } =\n this.#omegga.getRoleSetup();\n\n // host check if host has host color\n if (this.isHost() && bOwnerRoleHasColor)\n return color.rgbToHex(ownerRoleColor);\n\n // get the player's role\n const playerRoles = this.getRoles().map(r => r.toLowerCase());\n\n // only if the player actually has roles...\n if (playerRoles.length > 0) {\n // check the role list in reverse for the player's role (highest tier first)\n const found = roles\n .slice()\n .reverse()\n .find(\n role =>\n role.bHasColor && playerRoles.includes(role.name.toLowerCase()),\n );\n\n if (found) return color.rgbToHex(found.color);\n }\n\n return color.rgbToHex(\n defaultRole.bHasColor\n ? defaultRole.color\n : { r: 255, g: 255, b: 255, a: 255 },\n );\n }\n\n async getPawn(): Promise<string | null> {\n // given a player controller, match the player's pawn\n const pawnRegExp = new RegExp(\n `^(?<index>\\\\d+)\\\\) BP_PlayerController_C .+?PersistentLevel\\\\.${this.controller}\\\\.Pawn = .*?(?:BP_FigureV2_C'.+:PersistentLevel\\\\.)?(?<pawn>BP_FigureV2_C_\\\\d+|None)'?`,\n );\n\n // wait for the pawn watcher to return a pawn\n const [{ groups: { pawn = null } = {} } = {}] =\n await this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BP_PlayerController_C Pawn Name=' + this.controller,\n pawnRegExp,\n { first: 'index', timeoutDelay: 500 },\n );\n\n if (pawn === 'None') return null;\n\n return pawn;\n }\n\n async getPosition(): Promise<[number, number, number] | null> {\n // this is here because my text editor had weird syntax highlighting glitches when the other omeggas were replaced with this.#omegga...\n // guess the code is \"too new\" :egg:\n const omegga = this.#omegga;\n\n // given a player controller, match the player's pawn\n const pawnRegExp = new RegExp(\n `^(?<index>\\\\d+)\\\\) BP_PlayerController_C .+?PersistentLevel\\\\.${this.controller}\\\\.Pawn = .*?(?:BP_FigureV2_C'.+:PersistentLevel\\\\.)?(?<pawn>BP_FigureV2_C_\\\\d+|None)'?`,\n );\n\n // wait for the pawn watcher to return a pawn\n const [\n {\n groups: { pawn },\n },\n ] = await omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BP_PlayerController_C Pawn Name=' + this.controller,\n pawnRegExp,\n { first: 'index', timeoutDelay: 100 },\n );\n\n if (pawn === 'None') return null;\n\n // given a player's pawn, match the player's position\n const posRegExp = new RegExp(\n `CapsuleComponent .+?PersistentLevel\\\\.${pawn}\\\\.CollisionCylinder\\\\.RelativeLocation = \\\\(X=(?<x>[\\\\d\\\\.-]+),Y=(?<y>[\\\\d\\\\.-]+),Z=(?<z>[\\\\d\\\\.-]+)\\\\)`,\n );\n\n // wait for the position promise\n const [\n {\n groups: { x, y, z },\n },\n ] = await omegga.addWatcher(posRegExp, {\n // request the position for this player's pawn\n exec: () =>\n omegga.writeln(\n `GetAll SceneComponent RelativeLocation Name=CollisionCylinder Outer=${pawn}`,\n ),\n timeoutDelay: 100,\n });\n\n // return the player's position as an array of numbers\n return [Number(x), Number(y), Number(z)];\n }\n\n async getGhostBrick(): Promise<{\n targetGrid: string;\n location: number[];\n orientation: string;\n }> {\n const { controller } = this;\n\n const previewClass = 'BP_ToolPreviewActor_C';\n\n const ownerRegExp = new RegExp(\n `^(?<index>\\\\d+)\\\\) ${previewClass} (.+):PersistentLevel\\\\.(?<actor>${previewClass}_\\\\d+)\\.Owner = .*?BP_PlayerController_C'(.+):PersistentLevel\\\\.(?<controller>BP_PlayerController_C_\\\\d+)'$`,\n );\n const transformParamsRegExp = new RegExp(\n `^(?<index>\\\\d+)\\\\) ${previewClass} (.+):PersistentLevel\\\\.(?<actor>${previewClass}_\\\\d+)\\\\.TransformParameters = \\\\(TargetGrid=(\"(?<targetGrid>.+)\"|None),Location=\\\\(X=(?<x>.+),Y=(?<y>.+),Z=(?<z>.+)\\\\),Orientation=(?<orientation>.+)\\\\)$`,\n );\n\n const [owners, transformParams] = await Promise.all([\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n `GetAll ${previewClass} Owner`,\n ownerRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n `GetAll ${previewClass} TransformParameters`,\n transformParamsRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n ]);\n\n // get BrickGridPreviewActor by controller\n const owner = owners.find(owner => owner.groups.controller === controller);\n\n if (!owner) return;\n\n const actor = owner.groups.actor;\n // get transform parameters for the found actor\n const transformParameters = transformParams.find(\n transformParameters => transformParameters.groups.actor === actor,\n );\n\n if (!transformParameters) return;\n\n return {\n targetGrid: transformParameters.groups.targetGrid,\n location: [\n +transformParameters.groups.x,\n +transformParameters.groups.y,\n +transformParameters.groups.z,\n ],\n orientation: transformParameters.groups.orientation,\n };\n }\n\n async getPaint(): Promise<{\n materialIndex: string;\n materialAlpha: string;\n material: string;\n color: number[];\n }> {\n const { controller } = this;\n\n const match = await this.#omegga\n .addWatcher<{\n materialIndex: string;\n materialAlpha: string;\n material: string;\n color: number[];\n }>(\n line => {\n // [date][counter]0) BP_PlayerState_C /Game/Maps/Plate/Plate.Plate:PersistentLevel.BP_PlayerState_C_2147482378.ColorSelectionState = (SelectedColor=(B=6,G=73,R=246,A=255),MaterialIndex=3,MaterialAlpha=5)\n const match = line.match(\n /^\\[[^\\]]+\\]\\[[^\\]]+\\]\\d+\\) BP_PlayerState_C .+?PersistentLevel\\.(?<state>BP_PlayerState_C_\\d+)\\.ColorSelectionState = \\(SelectedColor=\\(B=(?<b>\\d+),G=(?<g>\\d+),R=(?<r>\\d+),A=(?<a>\\d+)\\),MaterialIndex=(?<materialIndex>\\d+),MaterialAlpha=(?<materialAlpha>\\d+)\\)$/,\n );\n if (!match) return;\n if (match.groups.state !== this.state) return;\n const colorRaw = [+match.groups.r, +match.groups.g, +match.groups.b];\n return {\n materialIndex: match.groups.materialIndex,\n materialAlpha: match.groups.materialAlpha,\n material:\n brickUtils.BRICK_CONSTANTS.DEFAULT_MATERIALS[\n Number(match.groups.materialIndex)\n ],\n color: colorRaw,\n };\n },\n {\n timeoutDelay: 1000,\n exec: () =>\n this.#omegga.writeln('GetAll BRPlayerState ColorSelectionState'),\n },\n )\n .catch(() => null);\n if (!match?.[0]) return;\n return match[0];\n }\n\n async isCrouched(pawn?: string): Promise<boolean> {\n if (!pawn) pawn = await this.getPawn();\n\n const reg =\n /(?<index>\\d+)\\) BP_FigureV2_C .+?PersistentLevel\\.(?<pawn>BP_FigureV2_C_\\d+)\\.bIsCrouched = (?<crouched>True|False)$/;\n\n const resp = await this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BP_FigureV2_C bIsCrouched Name=' + pawn,\n reg,\n { first: 'index', timeoutDelay: 500 },\n );\n\n const me = resp.find(r => r.groups.pawn === pawn);\n if (!me) return false;\n\n return me.groups.crouched == 'True';\n }\n\n async isDead(pawn?: string): Promise<boolean> {\n if (!pawn) pawn = await this.getPawn();\n\n const reg =\n /(?<index>\\d+)\\) BP_FigureV2_C .+?PersistentLevel\\.(?<pawn>BP_FigureV2_C_\\d+)\\.bIsDead = (?<dead>True|False)$/;\n\n const resp = await this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BP_FigureV2_C bIsDead Name=' + pawn,\n reg,\n { first: 'index', timeoutDelay: 500 },\n );\n\n const me = resp.find(r => r.groups.pawn === pawn);\n if (!me) return true;\n\n return me.groups.dead == 'True';\n }\n\n async getTemplateBounds() {\n const { controller } = this;\n\n const brickTemplateRegExp =\n /^(?<index>\\d+)\\) Tool_Selector_C (.+):PersistentLevel\\.(?<tool>Tool_Selector_C_\\d+)\\.CurrentTemplate = (.+)Brickadia.BrickBuildingTemplate'(.+)Transient.(?<templateName>BrickBuildingTemplate_\\d+)'$/;\n const brickTemplateOwnerRegExp =\n /^(?<index>\\d+)\\) Tool_Selector_C (.+):PersistentLevel\\.(?<tool>Tool_Selector_C_\\d+)\\.Owner = (.+)(?<controller>BP_PlayerController_C_\\d+)'$/;\n const minBoundsRegExp =\n /^(?<index>\\d+)\\) BrickBuildingTemplate (.+)Transient\\.(?<templateName>BrickBuildingTemplate_\\d+)\\.MinBounds = \\(X=(?<x>.+),Y=(?<y>.+),Z=(?<z>.+)\\)$/;\n const maxBoundsRegExp =\n /^(?<index>\\d+)\\) BrickBuildingTemplate (.+)Transient\\.(?<templateName>BrickBuildingTemplate_\\d+)\\.MaxBounds = \\(X=(?<x>.+),Y=(?<y>.+),Z=(?<z>.+)\\)$/;\n const centerRegExp =\n /^(?<index>\\d+)\\) BrickBuildingTemplate (.+)Transient\\.(?<templateName>BrickBuildingTemplate_\\d+)\\.Center = \\(X=(?<x>.+),Y=(?<y>.+),Z=(?<z>.+)\\)$/;\n\n const [templates, owners, minBounds, maxBounds, centers] =\n await Promise.all([\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll Tool_Selector_C CurrentTemplate',\n brickTemplateRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll Tool_Selector_C Owner',\n brickTemplateOwnerRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BrickBuildingTemplate MinBounds',\n minBoundsRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BrickBuildingTemplate MaxBounds',\n maxBoundsRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n this.#omegga.watchLogChunk<RegExpMatchArray>(\n 'GetAll BrickBuildingTemplate Center',\n centerRegExp,\n {\n first: 'index',\n timeoutDelay: 2000,\n afterMatchDelay: 100,\n },\n ),\n ]);\n\n if (\n !templates.length ||\n !owners.length ||\n !minBounds.length ||\n !maxBounds.length ||\n !centers.length\n )\n return;\n\n // get selector for this controller, we need to handle if there are multiple selectors for the same controller\n const selectors = owners\n .filter(selectors => selectors.groups.controller === controller)\n .map(selectors => selectors.groups.tool)\n .sort();\n const selector = selectors[0]; // grab the most recently created\n\n if (!selector) {\n return;\n }\n\n // template for this selector, we need to handle if there are multiple templates for the same selector and grab the most recent one\n const brickTemplates = templates\n .filter(template => template.groups.tool === selector)\n .map(template => template.groups.templateName)\n .sort();\n const templateName = brickTemplates[0]; // grab the most recently created\n\n if (!templateName) {\n return;\n }\n\n // find all values with matching template name\n const minBound = minBounds.find(\n minBound => minBound.groups.templateName === templateName,\n );\n const maxBound = maxBounds.find(\n maxBound => maxBound.groups.templateName === templateName,\n );\n const center = centers.find(\n center => center.groups.templateName === templateName,\n );\n\n if (!minBound || !maxBound || !center) return;\n\n return {\n minBound: [+minBound.groups.x, +minBound.groups.y, +minBound.groups.z],\n maxBound: [+maxBound.groups.x, +maxBound.groups.y, +maxBound.groups.z],\n center: [+center.groups.x, +center.groups.y, +center.groups.z],\n } as IBrickBounds;\n }\n\n async getTemplateBoundsData() {\n const templateBounds = await this.getTemplateBounds();\n\n if (!templateBounds) return;\n\n const saveData = await this.#omegga.getSaveData({\n center: templateBounds.center,\n extent: [\n Math.round(\n (templateBounds.maxBound[0] - templateBounds.minBound[0]) / 2,\n ),\n Math.round(\n (templateBounds.maxBound[1] - templateBounds.minBound[1]) / 2,\n ),\n Math.round(\n (templateBounds.maxBound[2] - templateBounds.minBound[2]) / 2,\n ),\n ],\n });\n\n if (!saveData) return;\n\n // filter bricks outside the bounds\n // no longer necessary thanks to Bricks.SaveRegion\n /* saveData.bricks = (saveData.bricks as Brick[]).filter(brick => {\n return brickUtils.checkBounds(\n brick,\n saveData.brick_assets,\n templateBounds\n );\n }) as typeof saveData.bricks; */\n\n if (saveData.bricks.length > 0) {\n return saveData;\n }\n\n return undefined;\n }\n\n loadBricks(saveName: string) {\n this.#omegga.loadBricksOnPlayer(saveName, this);\n }\n\n async loadSaveData(\n saveData: WriteSaveObject,\n { offX = 0, offY = 0, offZ = 0 } = {},\n ) {\n await this.#omegga.loadSaveDataOnPlayer(saveData, this, {\n offX,\n offY,\n offZ,\n });\n }\n\n async loadDataAtGhostBrick(\n saveData: WriteSaveObject,\n { rotate = true, offX = 0, offY = 0, offZ = 0, quiet = true } = {},\n ) {\n const ghostBrickData = await this.getGhostBrick();\n\n if (!ghostBrickData || !saveData) return;\n\n // get bounds of the bricks\n const bounds = brickUtils.getBounds(saveData);\n\n if (rotate) {\n const orientation =\n brickUtils.BRICK_CONSTANTS.orientationMap[ghostBrickData.orientation];\n saveData.bricks = saveData.bricks.map(brick =>\n brickUtils.rotate(brick, orientation),\n );\n // rotate bounds, if we dont use the original bounds they are off by 1 sometimes >:(\n bounds.minBound = brickUtils.BRICK_CONSTANTS.translationTable[\n brickUtils.d2o(...orientation)\n ](bounds.minBound);\n bounds.maxBound = brickUtils.BRICK_CONSTANTS.translationTable[\n brickUtils.d2o(...orientation)\n ](bounds.maxBound);\n bounds.center = brickUtils.BRICK_CONSTANTS.translationTable[\n brickUtils.d2o(...orientation)\n ](bounds.center);\n }\n\n // calculate offset from bricks center to ghost brick center\n const offset = bounds.center.map(\n (center, index) => ghostBrickData.location[index] - center,\n );\n\n // load at offset location\n await this.#omegga.loadSaveData(saveData, {\n offX: offX + offset[0],\n offY: offY + offset[1],\n offZ: offZ + offset[2],\n quiet,\n });\n }\n\n kill() {\n Player.kill(this.#omegga, this);\n }\n\n damage(amount: number): void {\n Player.damage(this.#omegga, this, amount);\n }\n\n heal(amount: number): void {\n Player.heal(this.#omegga, this, amount);\n }\n\n giveItem(item: WeaponClass): void {\n Player.giveItem(this.#omegga, this, item);\n }\n\n takeItem(item: WeaponClass): void {\n Player.takeItem(this.#omegga, this, item);\n }\n\n setTeam(teamIndex: number): void {\n Player.setTeam(this.#omegga, this, teamIndex);\n }\n\n setMinigame(index: number): void {\n Player.setMinigame(this.#omegga, this, index);\n }\n\n setScore(minigameIndex: number, score: number): void {\n Player.setScore(this.#omegga, this, minigameIndex, score);\n }\n\n getScore(minigameIndex: number): Promise<number> {\n return Player.getScore(this.#omegga, this, minigameIndex);\n }\n\n setLeaderboard(key: string, value: number): void {\n Player.setLeaderboard(this.#omegga, this, key, value);\n }\n\n async getLeaderboard(key: string): Promise<number | null> {\n return Player.getLeaderboard(this.#omegga, this, key);\n }\n}\n\nglobal.Player = Player;\n\nexport default Player;\n"],"names":["index","match","color","owner","transformParameters","brickUtils","selectors","minBound","maxBound","center"],"mappings":"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"}
@@ -468,10 +468,16 @@ class RpcPlugin extends _interface.Plugin {
468
468
  addPlayerMethod("getPermissions");
469
469
  addPlayerMethod("getNameColor");
470
470
  addPlayerMethod("getPosition");
471
+ addPlayerMethod("getPawn");
471
472
  addPlayerMethod("getGhostBrick");
472
473
  addPlayerMethod("getPaint");
474
+ addPlayerMethod("isCrouched");
475
+ addPlayerMethod("isDead");
473
476
  addPlayerMethod("getTemplateBounds");
474
477
  addPlayerMethod("getTemplateBoundsData");
478
+ addPlayerMethod("kill");
479
+ addPlayerMethod("getScore");
480
+ addPlayerMethod("getLeaderboard");
475
481
  rpc.addMethod(
476
482
  "player.loadDataAtGhostBrick",
477
483
  ({
@@ -494,6 +500,54 @@ class RpcPlugin extends _interface.Plugin {
494
500
  offZ = 0
495
501
  }) => this.omegga.getPlayer(target)?.loadSaveData(data, { offX, offY, offZ })
496
502
  );
503
+ rpc.addMethod(
504
+ "player.clearBricks",
505
+ ({ target, quiet = false }) => this.omegga.getPlayer(target)?.clearBricks(quiet)
506
+ );
507
+ rpc.addMethod(
508
+ "player.loadBricks",
509
+ ({ target, saveName }) => this.omegga.getPlayer(target)?.loadBricks(saveName)
510
+ );
511
+ rpc.addMethod(
512
+ "player.damage",
513
+ ({ target, amount }) => this.omegga.getPlayer(target)?.damage(amount)
514
+ );
515
+ rpc.addMethod(
516
+ "player.heal",
517
+ ({ target, amount }) => this.omegga.getPlayer(target)?.heal(amount)
518
+ );
519
+ rpc.addMethod(
520
+ "player.giveItem",
521
+ ({ target, item }) => this.omegga.getPlayer(target)?.giveItem(item)
522
+ );
523
+ rpc.addMethod(
524
+ "player.takeItem",
525
+ ({ target, item }) => this.omegga.getPlayer(target)?.takeItem(item)
526
+ );
527
+ rpc.addMethod(
528
+ "player.setTeam",
529
+ ({ target, teamIndex }) => this.omegga.getPlayer(target)?.setTeam(teamIndex)
530
+ );
531
+ rpc.addMethod(
532
+ "player.setMinigame",
533
+ ({ target, index }) => this.omegga.getPlayer(target)?.setMinigame(index)
534
+ );
535
+ rpc.addMethod(
536
+ "player.setScore",
537
+ ({
538
+ target,
539
+ minigameIndex,
540
+ score
541
+ }) => this.omegga.getPlayer(target)?.setScore(minigameIndex, score)
542
+ );
543
+ rpc.addMethod(
544
+ "player.setLeaderboard",
545
+ ({
546
+ target,
547
+ key,
548
+ value
549
+ }) => this.omegga.getPlayer(target)?.setLeaderboard(key, value)
550
+ );
497
551
  rpc.addMethod("plugin.get", async (name2) => {
498
552
  const plugin = this.omegga.pluginLoader.plugins.find(
499
553
  (p) => p.getName() === name2
@@ -1 +1 @@
1
- {"version":3,"file":"plugin_jsonrpc_stdio.js","sources":["../../../src/omegga/plugin/plugin_jsonrpc_stdio.ts"],"sourcesContent":["import Logger from '@/logger';\nimport { EnvironmentPreset } from '@brickadia/presets';\nimport Omegga from '@omegga/server';\nimport { WriteSaveObject } from 'brs-js';\nimport {\n JSONRPCClient,\n JSONRPCServer,\n JSONRPCServerAndClient,\n} from 'json-rpc-2.0';\nimport { ChildProcessWithoutNullStreams, spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport readline from 'readline';\nimport { Plugin } from './interface';\nimport { bootstrap } from './plugin_node_safe/proxyOmegga';\n\n// TODO: check if version is compatible (v1 -> v2) from file\n// TODO: write jsonrpc wrappers in a few languages, implement a few simple plugins\n// TODO: languages: [ python, go ]\n\nconst MAIN_FILE = 'omegga_plugin';\nconst DOC_FILE = 'doc.json';\nconst PLUGIN_FILE = 'plugin.json';\n\nexport default class RpcPlugin extends Plugin {\n #child: ChildProcessWithoutNullStreams;\n #rpc: JSONRPCServerAndClient;\n #errInterface: readline.Interface;\n #outInterface: readline.Interface;\n\n messageCounter: number;\n\n // all RPC plugins require a main (binary) file and a doc file\n static canLoad(pluginPath: string) {\n return (\n fs.existsSync(path.join(pluginPath, MAIN_FILE)) &&\n fs.existsSync(path.join(pluginPath, DOC_FILE))\n );\n }\n\n // websocket rpc plugin type\n static getFormat() {\n return 'jsonrpc_stdio';\n }\n\n // documentation is based on doc.json file\n getDocumentation() {\n return this.documentation;\n }\n constructor(pluginPath: string, omegga: Omegga) {\n super(pluginPath, omegga);\n\n this.messageCounter = 0;\n\n // TODO: validate documentation\n this.documentation = Plugin.readJSON(path.join(pluginPath, DOC_FILE));\n this.pluginConfig = Plugin.readJSON(path.join(pluginPath, PLUGIN_FILE));\n this.pluginFile = path.join(pluginPath, MAIN_FILE);\n\n this.eventPassthrough = this.eventPassthrough.bind(this);\n this.commands = [];\n\n this.initRPC();\n }\n\n isLoaded() {\n return !!this.#child && !this.#child.exitCode;\n }\n\n // determing if a command is registered\n isCommand(cmd: string) {\n return this.commands.includes(cmd);\n }\n\n // spawn the plugin as a child process\n async load() {\n const name = this.getName();\n const verbose = (...msg: any[]) => Logger.verbose(name.underline, ...msg);\n verbose('Load method invoked');\n let frozen = true,\n timed = false;\n this.commands = [];\n\n // can't load the plugin if the child is still running\n if (this.#child) {\n verbose('Plugin already has child process');\n return false;\n }\n\n let config;\n try {\n verbose('Getting plugin config');\n config = await this.storage.getConfig();\n } catch (e) {\n return false;\n }\n\n try {\n if (this.pluginConfig?.emitConfig) {\n verbose('Emitting plugin config');\n await fs.promises.writeFile(\n path.join(this.path, this.pluginConfig.emitConfig),\n JSON.stringify(config),\n );\n }\n verbose('Spawning child process');\n this.#child = spawn(this.pluginFile);\n this.#child.stdin.setDefaultEncoding('utf8');\n this.#outInterface = readline.createInterface({\n input: this.#child.stdout,\n terminal: false,\n });\n this.#errInterface = readline.createInterface({\n input: this.#child.stderr,\n terminal: false,\n });\n this.attachListeners();\n } catch (err) {\n Logger.errorp(\n 'error loading stdio rpc plugin',\n name.brightRed.underline,\n err,\n );\n await this.kill();\n this.emitStatus();\n return false;\n }\n\n return Promise.race([\n (async () => {\n try {\n // get some initial information to create an omegga proxy\n const initialData = bootstrap(this.omegga);\n\n verbose('Sending initial data');\n // send all of the mock events to the proxy omegga\n for (const ev in initialData) {\n // send some initial information\n this.notify(ev, initialData[ev]);\n }\n\n verbose('Initializing event passthrough');\n // pass events through\n this.omegga.on('*', this.eventPassthrough);\n\n try {\n // tell the plugin to start\n verbose('Waiting for plugin to start...');\n const result = await this.emit('init', config);\n\n verbose('Initialized with result:', result);\n // plugins can return a result object\n if (typeof result === 'object' && result) {\n // if registeredCommands is in the results, register the provided strings as commands\n const cmds = result.registeredCommands;\n if (\n cmds &&\n cmds instanceof Array &&\n cmds.every(i => typeof i === 'string')\n )\n this.commands = cmds;\n }\n } catch (e) {\n if (!e.message) return;\n Logger.errorp(name.brightRed.underline, 'error starting: ', e);\n }\n\n // plugin is not frozen, resolve that it has loaded\n frozen = false;\n if (timed) return;\n this.emitStatus();\n return true;\n } catch (e) {\n if (timed) return;\n Logger.errorp(\n 'error loading stdio rpc plugin',\n name.brightRed.underline,\n e,\n );\n await this.kill();\n frozen = false;\n this.emitStatus();\n return false;\n }\n })(),\n new Promise<boolean>(resolve => {\n // let user know if the child quit while launching\n this.#child.once('exit', () => {\n if (!frozen || timed) return;\n verbose('Plugin exited during init');\n frozen = false;\n this.emitStatus();\n resolve(false);\n });\n\n // check if the child is frozen (while true)\n setTimeout(() => {\n if (!frozen) return;\n Logger.errorp(\n 'I appear to be unresponsive when starting (maybe I forgot to respond to init)',\n name.brightRed.underline,\n );\n this.kill();\n timed = true;\n this.emitStatus();\n resolve(false);\n }, 5000);\n }),\n ]);\n }\n\n // kill the child process after requesting it to stop\n unload() {\n if (!this.#child || this.#child.exitCode) {\n this.detachListeners();\n this.emitStatus();\n return Promise.resolve(true);\n }\n let frozen = true,\n timed = false;\n const name = this.getName();\n\n return Promise.race([\n (async (): Promise<boolean> => {\n try {\n // let the plugin know it's time to stop, if this error it's probably because the method was not implemented\n try {\n await this.emit('stop');\n } catch (e) {\n // lazy developer - just implement stop please\n }\n\n await this.kill();\n\n frozen = false;\n if (timed) return;\n this.emitStatus();\n this.commands = [];\n return true;\n } catch (e) {\n if (timed) return;\n Logger.errorp(\n 'error unloading rpc plugin',\n name.brightRed.underline,\n e,\n );\n frozen = false;\n this.emitStatus();\n return false;\n }\n })(),\n // this is wrapped in a promise for the freeze check\n new Promise<boolean>(resolve => {\n // check if the child is frozen (while true)\n setTimeout(() => {\n if (!frozen) return;\n Logger.errorp(\n 'I appear to be unresponsive when stopping (maybe I forgot to respond to stop)',\n name.brightRed.underline,\n );\n this.kill();\n timed = true;\n this.emitStatus();\n resolve(true);\n }, 5000);\n }),\n ]);\n }\n\n // attaches event listeners\n attachListeners() {\n const name = this.getName();\n\n this.#outInterface.on('line', line => {\n try {\n const rpcData = JSON.parse(line);\n try {\n this.#rpc.receiveAndSend(rpcData);\n } catch (e) {\n Logger.error(\n this.getName().brightRed.underline,\n '!>'.red,\n 'error parsing rpc data',\n e,\n line,\n );\n }\n } catch {\n // fallback to logging\n Logger.log(name.underline, '>>'.green, line);\n }\n });\n\n // stderr - print out the errors\n this.#errInterface.on('line', err => {\n Logger.error(name.brightRed.underline, '!>'.red, err);\n });\n\n this.#child.on('error', () => this.kill());\n this.#child.on('close', () => this.kill());\n this.#child.on('exit', code => {\n Logger.errorp(\n '!>'.red,\n 'rpc plugin',\n name.brightRed.underline,\n 'exited with code',\n code,\n );\n this.kill();\n });\n }\n\n // removes previously attached event listeners\n detachListeners() {\n this.#outInterface.removeAllListeners('line');\n this.#errInterface.removeAllListeners('line');\n if (this.#child) {\n this.#child.removeAllListeners('exit');\n this.#child.removeAllListeners('close');\n this.#child.removeAllListeners('error');\n }\n }\n\n // write a string to the child process\n writeln(line: string) {\n try {\n if (this.#child && !this.#child.exitCode)\n this.#child.stdin.write(line + '\\n');\n } catch (e) {\n // the child probably died... oops!\n }\n }\n\n // forcibly kills the plugin\n async kill() {\n this.#rpc.rejectAllPendingRequests('Plugin Terminated');\n this.detachListeners();\n this.omegga.off('*', this.eventPassthrough);\n if (!this.#child) return;\n\n // create a promise for the exit of the process\n const promise = new Promise(resolve => this.#child.once('exit', resolve));\n\n // kill the process\n this.#child.kill('SIGINT');\n\n // ...kill it again just to make sure it's dead\n spawn('kill', ['-9', this.#child.pid + '']);\n\n // wait for the process to exit\n await promise;\n this.#child = undefined;\n this.emitStatus();\n }\n\n eventPassthrough(type: string, ...args: any[]) {\n if (!this.#child) return;\n this.notify(type, args);\n }\n\n // setup the JSONRPC communication\n initRPC() {\n const server = new JSONRPCServer();\n const client = new JSONRPCClient(req => {\n try {\n this.writeln(JSON.stringify(req));\n return Promise.resolve();\n } catch (error) {\n return Promise.reject(error);\n }\n });\n const rpc = (this.#rpc = new JSONRPCServerAndClient(server, client));\n\n // plugin log generator function\n const ezLog =\n (\n logFn: 'log' | 'error' | 'info' | 'debug' | 'warn' | 'trace',\n name: string,\n symbol: string,\n ) =>\n (line: any) =>\n console[logFn](name.underline, symbol, line);\n\n const name = this.getName();\n\n // server can output logs special formatting for stdout\n rpc.addMethod('log', ezLog('log', name, '>>'.green));\n rpc.addMethod('error', ezLog('error', name.brightRed, '!>'.red));\n rpc.addMethod('info', ezLog('info', name, '#>'.blue));\n rpc.addMethod('debug', ezLog('debug', name, '?>'.blue));\n rpc.addMethod('warn', ezLog('warn', name.brightYellow, ':>'.yellow));\n rpc.addMethod('trace', ezLog('trace', name, 'T>'.grey));\n\n // plugin store interactions\n rpc.addMethod('store.get', key =>\n this.storage.get(key as unknown as string),\n );\n rpc.addMethod('store.set', ([key, value]: [key: string, value: any]) =>\n this.storage.set(key, value),\n );\n rpc.addMethod('store.delete', key =>\n this.storage.delete(key as unknown as string),\n );\n rpc.addMethod('store.wipe', () => this.storage.wipe());\n rpc.addMethod('store.count', () => this.storage.count());\n rpc.addMethod('store.keys', () => this.storage.keys());\n\n // server can run console commands\n rpc.addMethod('exec', line =>\n this.omegga.writeln(line as unknown as string),\n );\n rpc.addMethod('writeln', line =>\n this.omegga.writeln(line as unknown as string),\n );\n rpc.addMethod('broadcast', line =>\n this.omegga.broadcast(line as unknown as string),\n );\n rpc.addMethod(\n 'whisper',\n ({ target, line }: { target: string; line: string }) =>\n this.omegga.whisper(target, line),\n );\n rpc.addMethod(\n 'middlePrint',\n ({ target, line }: { target: string; line: string }) =>\n this.omegga.middlePrint(target, line),\n );\n rpc.addMethod('getPlayers', () => this.omegga.getPlayers());\n rpc.addMethod('getPlayerPosition', name =>\n this.omegga.getPlayer(name as unknown as string)?.getPosition(),\n ); // included for compatibility\n rpc.addMethod('getAllPlayerPositions', () =>\n this.omegga.getAllPlayerPositions(),\n );\n rpc.addMethod('getEnvironmentPresets', () =>\n this.omegga.getEnvironmentPresets(),\n );\n rpc.addMethod('resetEnvironment', () => this.omegga.resetEnvironment());\n rpc.addMethod('saveEnvironment', name =>\n this.omegga.saveEnvironment(name as unknown as string),\n );\n rpc.addMethod('loadEnvironment', name =>\n this.omegga.loadEnvironment(name as unknown as string),\n );\n rpc.addMethod('loadEnvironmentData', data =>\n this.omegga.loadEnvironmentData(data as EnvironmentPreset),\n );\n rpc.addMethod('getServerStatus', () => this.omegga.getServerStatus());\n rpc.addMethod('getMinigames', () => this.omegga.getMinigames());\n rpc.addMethod('getMinigamePresets', () => this.omegga.getMinigamePresets());\n rpc.addMethod(\n 'saveMinigame',\n ({ index, name }: { index: number; name: string }) =>\n this.omegga.saveMinigame(index, name),\n );\n rpc.addMethod(\n 'loadMinigame',\n ({ name, owner }: { name: string; owner: string }) =>\n this.omegga.loadMinigame(name, owner),\n );\n rpc.addMethod('nextRoundMinigame', index =>\n this.omegga.nextRoundMinigame(index as unknown as number),\n );\n rpc.addMethod('resetMinigame', index =>\n this.omegga.resetMinigame(index as unknown as number),\n );\n rpc.addMethod('deleteMinigame', index =>\n this.omegga.deleteMinigame(index as unknown as number),\n );\n rpc.addMethod('listMinigames', () => this.omegga.listMinigames());\n rpc.addMethod('getHostId', () => this.omegga.getHostId());\n rpc.addMethod('getRoleSetup', () => this.omegga.getRoleSetup());\n rpc.addMethod('getBanList', () => this.omegga.getBanList());\n rpc.addMethod('getSaves', () => this.omegga.getSaves());\n rpc.addMethod('getSavePath', name =>\n this.omegga.getSavePath(name as unknown as string),\n );\n rpc.addMethod(\n 'clearBricks',\n ({ target, quiet = false }: { target: string; quiet?: boolean }) =>\n this.omegga.clearBricks(target, quiet),\n );\n rpc.addMethod('clearAllBricks', quiet =>\n this.omegga.clearAllBricks(quiet as unknown as boolean),\n );\n rpc.addMethod('saveBricks', name =>\n this.omegga.saveBricks(name as unknown as string),\n );\n rpc.addMethod(\n 'loadBricks',\n ({\n name,\n offX = 0,\n offY = 0,\n offZ = 0,\n quiet = false,\n }: {\n name: string;\n offX?: number;\n offY?: number;\n offZ?: number;\n quiet?: boolean;\n }) => this.omegga.loadBricks(name, { offX, offY, offZ, quiet }),\n );\n rpc.addMethod(\n 'loadBricksOnPlayer',\n ({\n name,\n player,\n offX = 0,\n offY = 0,\n offZ = 0,\n }: {\n name: string;\n player: string;\n offX?: number;\n offY?: number;\n offZ?: number;\n quiet?: boolean;\n }) => this.omegga.loadBricksOnPlayer(name, player, { offX, offY, offZ }),\n );\n rpc.addMethod('readSaveData', name =>\n this.omegga.readSaveData(name as unknown as string),\n );\n rpc.addMethod('getSaveData', () => this.omegga.getSaveData());\n rpc.addMethod(\n 'loadSaveData',\n ({\n data,\n offX = 0,\n offY = 0,\n offZ = 0,\n quiet = false,\n }: {\n data: WriteSaveObject;\n offX?: number;\n offY?: number;\n offZ?: number;\n quiet?: boolean;\n }) => this.omegga.loadSaveData(data, { offX, offY, offZ, quiet }),\n );\n rpc.addMethod(\n 'loadSaveDataOnPlayer',\n ({\n data,\n player,\n offX = 0,\n offY = 0,\n offZ = 0,\n }: {\n data: WriteSaveObject;\n player: string;\n offX?: number;\n offY?: number;\n offZ?: number;\n quiet?: boolean;\n }) =>\n this.omegga.loadSaveDataOnPlayer(data, player, { offX, offY, offZ }),\n );\n rpc.addMethod('changeMap', map =>\n this.omegga.changeMap(map as unknown as string),\n );\n rpc.addMethod('unload', () => this.unload());\n rpc.addMethod('reload', async () => {\n await this.unload();\n await this.load();\n });\n\n // player related operations\n const addPlayerMethod = (name: string) =>\n rpc.addMethod(`player.${name}`, player =>\n (this.omegga.getPlayer(player as unknown as string) as any)?.[name](),\n );\n rpc.addMethod('player.get', target => {\n let player = this.omegga.getPlayer(target as unknown as string);\n return player && { ...player, host: player.isHost() };\n });\n addPlayerMethod('getRoles');\n addPlayerMethod('getPermissions');\n addPlayerMethod('getNameColor');\n addPlayerMethod('getPosition');\n addPlayerMethod('getGhostBrick');\n addPlayerMethod('getPaint');\n addPlayerMethod('getTemplateBounds');\n addPlayerMethod('getTemplateBoundsData');\n rpc.addMethod(\n 'player.loadDataAtGhostBrick',\n ({\n target,\n data,\n rotate = true,\n offX = 0,\n offY = 0,\n offZ = 0,\n quiet = false,\n }: {\n target: string;\n data: WriteSaveObject;\n rotate?: boolean;\n offX?: number;\n offY?: number;\n offZ?: number;\n quiet?: boolean;\n }) =>\n this.omegga\n .getPlayer(target)\n ?.loadDataAtGhostBrick(data, { rotate, offX, offY, offZ, quiet }),\n );\n rpc.addMethod(\n 'player.loadSaveData',\n ({\n target,\n data,\n offX = 0,\n offY = 0,\n offZ = 0,\n }: {\n target: string;\n data: WriteSaveObject;\n offX?: number;\n offY?: number;\n offZ?: number;\n }) =>\n this.omegga.getPlayer(target)?.loadSaveData(data, { offX, offY, offZ }),\n );\n\n // plugin related operations\n rpc.addMethod('plugin.get', async name => {\n const plugin = this.omegga.pluginLoader.plugins.find(\n p => p.getName() === (name as unknown as string),\n );\n\n if (plugin) {\n return {\n name,\n documentation: plugin.getDocumentation(),\n loaded: plugin.isLoaded(),\n };\n } else {\n return null;\n }\n });\n\n rpc.addMethod(\n 'plugin.emit',\n async ([name, event, ...args]: [string, string, ...any[]]) => {\n const plugin = this.omegga.pluginLoader.plugins.find(\n p => p.getName() === name,\n );\n\n if (plugin) {\n return plugin.emitPlugin(event, this.getName(), args);\n } else {\n return null;\n }\n },\n );\n }\n\n // emit a custom plugin event\n async emitPlugin(event: string, from: string, args: any[]) {\n return await this.emit('plugin:emit', [event, from, ...args]);\n }\n\n // emit a message to the plugin via the jsonrpc client and expect a response\n emit(type: string, arg?: any) {\n return this.#rpc.request(type, arg);\n }\n\n // emit a message to the plugin via the jsonrpc client, don't expect a response\n notify(type: string, arg?: any) {\n try {\n this.#rpc.notify(type, arg);\n } catch (e) {\n // this only happens if the RPC library is hitting some issues - probably redundant\n }\n }\n}\n"],"names":["Plugin","Logger","spawn","bootstrap","JSONRPCServer","JSONRPCClient","JSONRPCServerAndClient","name"],"mappings":"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"}
1
+ {"version":3,"file":"plugin_jsonrpc_stdio.js","sources":["../../../src/omegga/plugin/plugin_jsonrpc_stdio.ts"],"sourcesContent":["import Logger from '@/logger';\nimport { EnvironmentPreset } from '@brickadia/presets';\nimport Omegga from '@omegga/server';\nimport { WriteSaveObject } from 'brs-js';\nimport {\n JSONRPCClient,\n JSONRPCServer,\n JSONRPCServerAndClient,\n} from 'json-rpc-2.0';\nimport { ChildProcessWithoutNullStreams, spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport readline from 'readline';\nimport { Plugin } from './interface';\nimport { bootstrap } from './plugin_node_safe/proxyOmegga';\n\n// TODO: check if version is compatible (v1 -> v2) from file\n// TODO: write jsonrpc wrappers in a few languages, implement a few simple plugins\n// TODO: languages: [ python, go ]\n\nconst MAIN_FILE = 'omegga_plugin';\nconst DOC_FILE = 'doc.json';\nconst PLUGIN_FILE = 'plugin.json';\n\nexport default class RpcPlugin extends Plugin {\n #child: ChildProcessWithoutNullStreams;\n #rpc: JSONRPCServerAndClient;\n #errInterface: readline.Interface;\n #outInterface: readline.Interface;\n\n messageCounter: number;\n\n // all RPC plugins require a main (binary) file and a doc file\n static canLoad(pluginPath: string) {\n return (\n fs.existsSync(path.join(pluginPath, MAIN_FILE)) &&\n fs.existsSync(path.join(pluginPath, DOC_FILE))\n );\n }\n\n // websocket rpc plugin type\n static getFormat() {\n return 'jsonrpc_stdio';\n }\n\n // documentation is based on doc.json file\n getDocumentation() {\n return this.documentation;\n }\n constructor(pluginPath: string, omegga: Omegga) {\n super(pluginPath, omegga);\n\n this.messageCounter = 0;\n\n // TODO: validate documentation\n this.documentation = Plugin.readJSON(path.join(pluginPath, DOC_FILE));\n this.pluginConfig = Plugin.readJSON(path.join(pluginPath, PLUGIN_FILE));\n this.pluginFile = path.join(pluginPath, MAIN_FILE);\n\n this.eventPassthrough = this.eventPassthrough.bind(this);\n this.commands = [];\n\n this.initRPC();\n }\n\n isLoaded() {\n return !!this.#child && !this.#child.exitCode;\n }\n\n // determing if a command is registered\n isCommand(cmd: string) {\n return this.commands.includes(cmd);\n }\n\n // spawn the plugin as a child process\n async load() {\n const name = this.getName();\n const verbose = (...msg: any[]) => Logger.verbose(name.underline, ...msg);\n verbose('Load method invoked');\n let frozen = true,\n timed = false;\n this.commands = [];\n\n // can't load the plugin if the child is still running\n if (this.#child) {\n verbose('Plugin already has child process');\n return false;\n }\n\n let config;\n try {\n verbose('Getting plugin config');\n config = await this.storage.getConfig();\n } catch (e) {\n return false;\n }\n\n try {\n if (this.pluginConfig?.emitConfig) {\n verbose('Emitting plugin config');\n await fs.promises.writeFile(\n path.join(this.path, this.pluginConfig.emitConfig),\n JSON.stringify(config),\n );\n }\n verbose('Spawning child process');\n this.#child = spawn(this.pluginFile);\n this.#child.stdin.setDefaultEncoding('utf8');\n this.#outInterface = readline.createInterface({\n input: this.#child.stdout,\n terminal: false,\n });\n this.#errInterface = readline.createInterface({\n input: this.#child.stderr,\n terminal: false,\n });\n this.attachListeners();\n } catch (err) {\n Logger.errorp(\n 'error loading stdio rpc plugin',\n name.brightRed.underline,\n err,\n );\n await this.kill();\n this.emitStatus();\n return false;\n }\n\n return Promise.race([\n (async () => {\n try {\n // get some initial information to create an omegga proxy\n const initialData = bootstrap(this.omegga);\n\n verbose('Sending initial data');\n // send all of the mock events to the proxy omegga\n for (const ev in initialData) {\n // send some initial information\n this.notify(ev, initialData[ev]);\n }\n\n verbose('Initializing event passthrough');\n // pass events through\n this.omegga.on('*', this.eventPassthrough);\n\n try {\n // tell the plugin to start\n verbose('Waiting for plugin to start...');\n const result = await this.emit('init', config);\n\n verbose('Initialized with result:', result);\n // plugins can return a result object\n if (typeof result === 'object' && result) {\n // if registeredCommands is in the results, register the provided strings as commands\n const cmds = result.registeredCommands;\n if (\n cmds &&\n cmds instanceof Array &&\n cmds.every(i => typeof i === 'string')\n )\n this.commands = cmds;\n }\n } catch (e) {\n if (!e.message) return;\n Logger.errorp(name.brightRed.underline, 'error starting: ', e);\n }\n\n // plugin is not frozen, resolve that it has loaded\n frozen = false;\n if (timed) return;\n this.emitStatus();\n return true;\n } catch (e) {\n if (timed) return;\n Logger.errorp(\n 'error loading stdio rpc plugin',\n name.brightRed.underline,\n e,\n );\n await this.kill();\n frozen = false;\n this.emitStatus();\n return false;\n }\n })(),\n new Promise<boolean>(resolve => {\n // let user know if the child quit while launching\n this.#child.once('exit', () => {\n if (!frozen || timed) return;\n verbose('Plugin exited during init');\n frozen = false;\n this.emitStatus();\n resolve(false);\n });\n\n // check if the child is frozen (while true)\n setTimeout(() => {\n if (!frozen) return;\n Logger.errorp(\n 'I appear to be unresponsive when starting (maybe I forgot to respond to init)',\n name.brightRed.underline,\n );\n this.kill();\n timed = true;\n this.emitStatus();\n resolve(false);\n }, 5000);\n }),\n ]);\n }\n\n // kill the child process after requesting it to stop\n unload() {\n if (!this.#child || this.#child.exitCode) {\n this.detachListeners();\n this.emitStatus();\n return Promise.resolve(true);\n }\n let frozen = true,\n timed = false;\n const name = this.getName();\n\n return Promise.race([\n (async (): Promise<boolean> => {\n try {\n // let the plugin know it's time to stop, if this error it's probably because the method was not implemented\n try {\n await this.emit('stop');\n } catch (e) {\n // lazy developer - just implement stop please\n }\n\n await this.kill();\n\n frozen = false;\n if (timed) return;\n this.emitStatus();\n this.commands = [];\n return true;\n } catch (e) {\n if (timed) return;\n Logger.errorp(\n 'error unloading rpc plugin',\n name.brightRed.underline,\n e,\n );\n frozen = false;\n this.emitStatus();\n return false;\n }\n })(),\n // this is wrapped in a promise for the freeze check\n new Promise<boolean>(resolve => {\n // check if the child is frozen (while true)\n setTimeout(() => {\n if (!frozen) return;\n Logger.errorp(\n 'I appear to be unresponsive when stopping (maybe I forgot to respond to stop)',\n name.brightRed.underline,\n );\n this.kill();\n timed = true;\n this.emitStatus();\n resolve(true);\n }, 5000);\n }),\n ]);\n }\n\n // attaches event listeners\n attachListeners() {\n const name = this.getName();\n\n this.#outInterface.on('line', line => {\n try {\n const rpcData = JSON.parse(line);\n try {\n this.#rpc.receiveAndSend(rpcData);\n } catch (e) {\n Logger.error(\n this.getName().brightRed.underline,\n '!>'.red,\n 'error parsing rpc data',\n e,\n line,\n );\n }\n } catch {\n // fallback to logging\n Logger.log(name.underline, '>>'.green, line);\n }\n });\n\n // stderr - print out the errors\n this.#errInterface.on('line', err => {\n Logger.error(name.brightRed.underline, '!>'.red, err);\n });\n\n this.#child.on('error', () => this.kill());\n this.#child.on('close', () => this.kill());\n this.#child.on('exit', code => {\n Logger.errorp(\n '!>'.red,\n 'rpc plugin',\n name.brightRed.underline,\n 'exited with code',\n code,\n );\n this.kill();\n });\n }\n\n // removes previously attached event listeners\n detachListeners() {\n this.#outInterface.removeAllListeners('line');\n this.#errInterface.removeAllListeners('line');\n if (this.#child) {\n this.#child.removeAllListeners('exit');\n this.#child.removeAllListeners('close');\n this.#child.removeAllListeners('error');\n }\n }\n\n // write a string to the child process\n writeln(line: string) {\n try {\n if (this.#child && !this.#child.exitCode)\n this.#child.stdin.write(line + '\\n');\n } catch (e) {\n // the child probably died... oops!\n }\n }\n\n // forcibly kills the plugin\n async kill() {\n this.#rpc.rejectAllPendingRequests('Plugin Terminated');\n this.detachListeners();\n this.omegga.off('*', this.eventPassthrough);\n if (!this.#child) return;\n\n // create a promise for the exit of the process\n const promise = new Promise(resolve => this.#child.once('exit', resolve));\n\n // kill the process\n this.#child.kill('SIGINT');\n\n // ...kill it again just to make sure it's dead\n spawn('kill', ['-9', this.#child.pid + '']);\n\n // wait for the process to exit\n await promise;\n this.#child = undefined;\n this.emitStatus();\n }\n\n eventPassthrough(type: string, ...args: any[]) {\n if (!this.#child) return;\n this.notify(type, args);\n }\n\n // setup the JSONRPC communication\n initRPC() {\n const server = new JSONRPCServer();\n const client = new JSONRPCClient(req => {\n try {\n this.writeln(JSON.stringify(req));\n return Promise.resolve();\n } catch (error) {\n return Promise.reject(error);\n }\n });\n const rpc = (this.#rpc = new JSONRPCServerAndClient(server, client));\n\n // plugin log generator function\n const ezLog =\n (\n logFn: 'log' | 'error' | 'info' | 'debug' | 'warn' | 'trace',\n name: string,\n symbol: string,\n ) =>\n (line: any) =>\n console[logFn](name.underline, symbol, line);\n\n const name = this.getName();\n\n // server can output logs special formatting for stdout\n rpc.addMethod('log', ezLog('log', name, '>>'.green));\n rpc.addMethod('error', ezLog('error', name.brightRed, '!>'.red));\n rpc.addMethod('info', ezLog('info', name, '#>'.blue));\n rpc.addMethod('debug', ezLog('debug', name, '?>'.blue));\n rpc.addMethod('warn', ezLog('warn', name.brightYellow, ':>'.yellow));\n rpc.addMethod('trace', ezLog('trace', name, 'T>'.grey));\n\n // plugin store interactions\n rpc.addMethod('store.get', key =>\n this.storage.get(key as unknown as string),\n );\n rpc.addMethod('store.set', ([key, value]: [key: string, value: any]) =>\n this.storage.set(key, value),\n );\n rpc.addMethod('store.delete', key =>\n this.storage.delete(key as unknown as string),\n );\n rpc.addMethod('store.wipe', () => this.storage.wipe());\n rpc.addMethod('store.count', () => this.storage.count());\n rpc.addMethod('store.keys', () => this.storage.keys());\n\n // server can run console commands\n rpc.addMethod('exec', line =>\n this.omegga.writeln(line as unknown as string),\n );\n rpc.addMethod('writeln', line =>\n this.omegga.writeln(line as unknown as string),\n );\n rpc.addMethod('broadcast', line =>\n this.omegga.broadcast(line as unknown as string),\n );\n rpc.addMethod(\n 'whisper',\n ({ target, line }: { target: string; line: string }) =>\n this.omegga.whisper(target, line),\n );\n rpc.addMethod(\n 'middlePrint',\n ({ target, line }: { target: string; line: string }) =>\n this.omegga.middlePrint(target, line),\n );\n rpc.addMethod('getPlayers', () => this.omegga.getPlayers());\n rpc.addMethod('getPlayerPosition', name =>\n this.omegga.getPlayer(name as unknown as string)?.getPosition(),\n ); // included for compatibility\n rpc.addMethod('getAllPlayerPositions', () =>\n this.omegga.getAllPlayerPositions(),\n );\n rpc.addMethod('getEnvironmentPresets', () =>\n this.omegga.getEnvironmentPresets(),\n );\n rpc.addMethod('resetEnvironment', () => this.omegga.resetEnvironment());\n rpc.addMethod('saveEnvironment', name =>\n this.omegga.saveEnvironment(name as unknown as string),\n );\n rpc.addMethod('loadEnvironment', name =>\n this.omegga.loadEnvironment(name as unknown as string),\n );\n rpc.addMethod('loadEnvironmentData', data =>\n this.omegga.loadEnvironmentData(data as EnvironmentPreset),\n );\n rpc.addMethod('getServerStatus', () => this.omegga.getServerStatus());\n rpc.addMethod('getMinigames', () => this.omegga.getMinigames());\n rpc.addMethod('getMinigamePresets', () => this.omegga.getMinigamePresets());\n rpc.addMethod(\n 'saveMinigame',\n ({ index, name }: { index: number; name: string }) =>\n this.omegga.saveMinigame(index, name),\n );\n rpc.addMethod(\n 'loadMinigame',\n ({ name, owner }: { name: string; owner: string }) =>\n this.omegga.loadMinigame(name, owner),\n );\n rpc.addMethod('nextRoundMinigame', index =>\n this.omegga.nextRoundMinigame(index as unknown as number),\n );\n rpc.addMethod('resetMinigame', index =>\n this.omegga.resetMinigame(index as unknown as number),\n );\n rpc.addMethod('deleteMinigame', index =>\n this.omegga.deleteMinigame(index as unknown as number),\n );\n rpc.addMethod('listMinigames', () => this.omegga.listMinigames());\n rpc.addMethod('getHostId', () => this.omegga.getHostId());\n rpc.addMethod('getRoleSetup', () => this.omegga.getRoleSetup());\n rpc.addMethod('getBanList', () => this.omegga.getBanList());\n rpc.addMethod('getSaves', () => this.omegga.getSaves());\n rpc.addMethod('getSavePath', name =>\n this.omegga.getSavePath(name as unknown as string),\n );\n rpc.addMethod(\n 'clearBricks',\n ({ target, quiet = false }: { target: string; quiet?: boolean }) =>\n this.omegga.clearBricks(target, quiet),\n );\n rpc.addMethod('clearAllBricks', quiet =>\n this.omegga.clearAllBricks(quiet as unknown as boolean),\n );\n rpc.addMethod('saveBricks', name =>\n this.omegga.saveBricks(name as unknown as string),\n );\n rpc.addMethod(\n 'loadBricks',\n ({\n name,\n offX = 0,\n offY = 0,\n offZ = 0,\n quiet = false,\n }: {\n name: string;\n offX?: number;\n offY?: number;\n offZ?: number;\n quiet?: boolean;\n }) => this.omegga.loadBricks(name, { offX, offY, offZ, quiet }),\n );\n rpc.addMethod(\n 'loadBricksOnPlayer',\n ({\n name,\n player,\n offX = 0,\n offY = 0,\n offZ = 0,\n }: {\n name: string;\n player: string;\n offX?: number;\n offY?: number;\n offZ?: number;\n quiet?: boolean;\n }) => this.omegga.loadBricksOnPlayer(name, player, { offX, offY, offZ }),\n );\n rpc.addMethod('readSaveData', name =>\n this.omegga.readSaveData(name as unknown as string),\n );\n rpc.addMethod('getSaveData', () => this.omegga.getSaveData());\n rpc.addMethod(\n 'loadSaveData',\n ({\n data,\n offX = 0,\n offY = 0,\n offZ = 0,\n quiet = false,\n }: {\n data: WriteSaveObject;\n offX?: number;\n offY?: number;\n offZ?: number;\n quiet?: boolean;\n }) => this.omegga.loadSaveData(data, { offX, offY, offZ, quiet }),\n );\n rpc.addMethod(\n 'loadSaveDataOnPlayer',\n ({\n data,\n player,\n offX = 0,\n offY = 0,\n offZ = 0,\n }: {\n data: WriteSaveObject;\n player: string;\n offX?: number;\n offY?: number;\n offZ?: number;\n quiet?: boolean;\n }) =>\n this.omegga.loadSaveDataOnPlayer(data, player, { offX, offY, offZ }),\n );\n rpc.addMethod('changeMap', map =>\n this.omegga.changeMap(map as unknown as string),\n );\n rpc.addMethod('unload', () => this.unload());\n rpc.addMethod('reload', async () => {\n await this.unload();\n await this.load();\n });\n\n // player related operations\n const addPlayerMethod = (name: string) =>\n rpc.addMethod(`player.${name}`, player =>\n (this.omegga.getPlayer(player as unknown as string) as any)?.[name](),\n );\n rpc.addMethod('player.get', target => {\n let player = this.omegga.getPlayer(target as unknown as string);\n return player && { ...player, host: player.isHost() };\n });\n addPlayerMethod('getRoles');\n addPlayerMethod('getPermissions');\n addPlayerMethod('getNameColor');\n addPlayerMethod('getPosition');\n addPlayerMethod('getPawn');\n addPlayerMethod('getGhostBrick');\n addPlayerMethod('getPaint');\n addPlayerMethod('isCrouched');\n addPlayerMethod('isDead');\n addPlayerMethod('getTemplateBounds');\n addPlayerMethod('getTemplateBoundsData');\n addPlayerMethod('kill');\n addPlayerMethod('getScore');\n addPlayerMethod('getLeaderboard');\n rpc.addMethod(\n 'player.loadDataAtGhostBrick',\n ({\n target,\n data,\n rotate = true,\n offX = 0,\n offY = 0,\n offZ = 0,\n quiet = false,\n }: {\n target: string;\n data: WriteSaveObject;\n rotate?: boolean;\n offX?: number;\n offY?: number;\n offZ?: number;\n quiet?: boolean;\n }) =>\n this.omegga\n .getPlayer(target)\n ?.loadDataAtGhostBrick(data, { rotate, offX, offY, offZ, quiet }),\n );\n rpc.addMethod(\n 'player.loadSaveData',\n ({\n target,\n data,\n offX = 0,\n offY = 0,\n offZ = 0,\n }: {\n target: string;\n data: WriteSaveObject;\n offX?: number;\n offY?: number;\n offZ?: number;\n }) =>\n this.omegga.getPlayer(target)?.loadSaveData(data, { offX, offY, offZ }),\n );\n rpc.addMethod(\n 'player.clearBricks',\n ({ target, quiet = false }: { target: string; quiet?: boolean }) =>\n this.omegga.getPlayer(target)?.clearBricks(quiet),\n );\n rpc.addMethod(\n 'player.loadBricks',\n ({ target, saveName }: { target: string; saveName: string }) =>\n this.omegga.getPlayer(target)?.loadBricks(saveName),\n );\n rpc.addMethod(\n 'player.damage',\n ({ target, amount }: { target: string; amount: number }) =>\n this.omegga.getPlayer(target)?.damage(amount),\n );\n rpc.addMethod(\n 'player.heal',\n ({ target, amount }: { target: string; amount: number }) =>\n this.omegga.getPlayer(target)?.heal(amount),\n );\n rpc.addMethod(\n 'player.giveItem',\n ({ target, item }: { target: string; item: string }) =>\n this.omegga.getPlayer(target)?.giveItem(item as any),\n );\n rpc.addMethod(\n 'player.takeItem',\n ({ target, item }: { target: string; item: string }) =>\n this.omegga.getPlayer(target)?.takeItem(item as any),\n );\n rpc.addMethod(\n 'player.setTeam',\n ({ target, teamIndex }: { target: string; teamIndex: number }) =>\n this.omegga.getPlayer(target)?.setTeam(teamIndex),\n );\n rpc.addMethod(\n 'player.setMinigame',\n ({ target, index }: { target: string; index: number }) =>\n this.omegga.getPlayer(target)?.setMinigame(index),\n );\n rpc.addMethod(\n 'player.setScore',\n ({\n target,\n minigameIndex,\n score,\n }: {\n target: string;\n minigameIndex: number;\n score: number;\n }) => this.omegga.getPlayer(target)?.setScore(minigameIndex, score),\n );\n rpc.addMethod(\n 'player.setLeaderboard',\n ({\n target,\n key,\n value,\n }: {\n target: string;\n key: string;\n value: number;\n }) => this.omegga.getPlayer(target)?.setLeaderboard(key, value),\n );\n\n // plugin related operations\n rpc.addMethod('plugin.get', async name => {\n const plugin = this.omegga.pluginLoader.plugins.find(\n p => p.getName() === (name as unknown as string),\n );\n\n if (plugin) {\n return {\n name,\n documentation: plugin.getDocumentation(),\n loaded: plugin.isLoaded(),\n };\n } else {\n return null;\n }\n });\n\n rpc.addMethod(\n 'plugin.emit',\n async ([name, event, ...args]: [string, string, ...any[]]) => {\n const plugin = this.omegga.pluginLoader.plugins.find(\n p => p.getName() === name,\n );\n\n if (plugin) {\n return plugin.emitPlugin(event, this.getName(), args);\n } else {\n return null;\n }\n },\n );\n }\n\n // emit a custom plugin event\n async emitPlugin(event: string, from: string, args: any[]) {\n return await this.emit('plugin:emit', [event, from, ...args]);\n }\n\n // emit a message to the plugin via the jsonrpc client and expect a response\n emit(type: string, arg?: any) {\n return this.#rpc.request(type, arg);\n }\n\n // emit a message to the plugin via the jsonrpc client, don't expect a response\n notify(type: string, arg?: any) {\n try {\n this.#rpc.notify(type, arg);\n } catch (e) {\n // this only happens if the RPC library is hitting some issues - probably redundant\n }\n }\n}\n"],"names":["Plugin","Logger","spawn","bootstrap","JSONRPCServer","JSONRPCClient","JSONRPCServerAndClient","name"],"mappings":"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"}
@@ -108,6 +108,12 @@ class NodePlugin extends _interface.Plugin {
108
108
  return false;
109
109
  }
110
110
  }
111
+ // forward plugin events to the loaded plugin instance
112
+ async emitPlugin(ev, from, args) {
113
+ if (typeof this.loadedPlugin?.pluginEvent === "function") {
114
+ return await this.loadedPlugin.pluginEvent(ev, from, ...args);
115
+ }
116
+ }
111
117
  // disrequire all that match plugin path in require.cache
112
118
  disrequireAll() {
113
119
  const requiredFiles = Object.keys(require.cache).filter(
@@ -1 +1 @@
1
- {"version":3,"file":"plugin_node_unsafe.js","sources":["../../../src/omegga/plugin/plugin_node_unsafe.ts"],"sourcesContent":["import Logger from '@/logger';\nimport OmeggaPlugin, { PluginStore } from '@/plugin';\nimport type Omegga from '@omegga/server';\nimport * as util from '@util';\nimport disrequire from 'disrequire';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { Plugin } from './interface';\n\nglobal.OMEGGA_UTIL = util;\n\n// Main plugin file (like index.js)\n// this isn't named 'index.js' or 'plugin.js' because those may be filenames\n// used with other loaders (rpc loader) and are too generic\n// omegga.main.js is rather unique and helps avoid collision\nconst MAIN_FILE = 'omegga.main.js';\n\n// Documentation file (contains name, description, author, command helptext)\nconst DOC_FILE = 'doc.json';\nconst PLUGIN_FILE = 'plugin.json';\n\nexport default class NodePlugin extends Plugin {\n // every node plugin requires the main file and a doc file\n // may evolve this so it checks the contents of the doc file later\n static canLoad(pluginPath: string) {\n return (\n fs.existsSync(path.join(pluginPath, MAIN_FILE)) &&\n fs.existsSync(path.join(pluginPath, DOC_FILE))\n );\n }\n\n // unsafe node plugins (can potentially crash omegga) are powerful\n static getFormat() {\n return 'node_unsafe';\n }\n\n constructor(pluginPath: string, omegga: Omegga) {\n super(pluginPath, omegga);\n // TODO: validate documentation\n this.documentation = Plugin.readJSON(path.join(pluginPath, DOC_FILE));\n this.pluginConfig = Plugin.readJSON(path.join(pluginPath, PLUGIN_FILE));\n this.pluginFile = path.join(pluginPath, MAIN_FILE);\n\n // list of registered comands\n this.commands = [];\n }\n\n // documentation is based on doc.json file\n getDocumentation() {\n return this.documentation;\n }\n\n // loaded state is based on if the loadedPlugin object is created\n isLoaded() {\n return !!this.loadedPlugin;\n }\n\n // determing if a command is registered\n isCommand(cmd: string) {\n return this.commands.includes(cmd);\n }\n\n // require the plugin into the system, run the init func\n async load() {\n const stopPlugin = (reason?: string) => {\n Logger.errorp('error launching node plugin', this.getName(), ':', reason);\n try {\n this.disrequireAll();\n } catch (e) {\n Logger.errorp('error unloading node plugin (2)', this.getName(), e);\n }\n this.emitStatus();\n return false;\n };\n this.commands = [];\n\n try {\n const config = await this.storage.getConfig();\n if (this.pluginConfig?.emitConfig) {\n await fs.promises.writeFile(\n path.join(this.path, this.pluginConfig.emitConfig),\n JSON.stringify(config),\n );\n }\n\n // require the plugin itself\n const Plugin: OmeggaPlugin = require(this.pluginFile);\n\n // node plugins must export a class with a constructor\n if (\n typeof (Plugin as any).prototype !== 'object' ||\n typeof (Plugin as any).prototype.constructor !== 'function'\n )\n return stopPlugin('missing constructor in plugin');\n\n // interface with plugin store\n const store: PluginStore = {\n get: key => this.storage.get(key),\n set: (key, value) => this.storage.set(key, value),\n delete: key => this.storage.delete(key),\n wipe: () => this.storage.wipe(),\n count: () => this.storage.count(),\n keys: () => this.storage.keys(),\n };\n\n // create the loaded plugin\n this.loadedPlugin = new (Plugin as any)(this.omegga, config, store);\n\n // start the loaded plugin\n if (typeof this.loadedPlugin.init === 'function') {\n const result = await this.loadedPlugin.init();\n\n // plugins can return a result object\n if (typeof result === 'object' && result) {\n // if registeredCommands is in the results, register the provided strings as commands\n const cmds = result.registeredCommands;\n if (\n cmds &&\n cmds instanceof Array &&\n cmds.every(i => typeof i === 'string')\n )\n this.commands = cmds;\n }\n }\n\n this.emitStatus();\n return true;\n } catch (e) {\n Logger.errorp('error loading node plugin', this.getName(), e);\n this.emitStatus();\n return false;\n }\n }\n\n // disrequire the plugin into the system, run the stop func\n async unload() {\n // can't unload the plugin if it hasn't been loaded\n if (typeof this.loadedPlugin === 'undefined') {\n this.emitStatus();\n return false;\n }\n\n try {\n // run the stop func on the plugin if applicable\n if (typeof this.loadedPlugin.stop === 'function')\n await this.loadedPlugin.stop();\n\n // unload the plugin\n this.disrequireAll();\n this.loadedPlugin = undefined;\n this.emitStatus();\n this.commands = [];\n return true;\n } catch (e) {\n Logger.errorp('error unloading node plugin', this.getName(), e);\n this.emitStatus();\n return false;\n }\n }\n\n // disrequire all that match plugin path in require.cache\n disrequireAll() {\n // get all files in plugin directory from require cache\n const requiredFiles = Object.keys(require.cache).filter(requiredFile =>\n requiredFile.includes(this.path),\n );\n // disrequire all the files\n requiredFiles.forEach(file => {\n try {\n disrequire(file);\n } catch (e) {\n if (e.code !== 'MODULE_NOT_FOUND')\n // ignore error thrown if a module was deleted\n throw e;\n }\n });\n }\n}\n"],"names":["util","Plugin","Logger"],"mappings":"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"}
1
+ {"version":3,"file":"plugin_node_unsafe.js","sources":["../../../src/omegga/plugin/plugin_node_unsafe.ts"],"sourcesContent":["import Logger from '@/logger';\nimport OmeggaPlugin, { PluginStore } from '@/plugin';\nimport type Omegga from '@omegga/server';\nimport * as util from '@util';\nimport disrequire from 'disrequire';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { Plugin } from './interface';\n\nglobal.OMEGGA_UTIL = util;\n\n// Main plugin file (like index.js)\n// this isn't named 'index.js' or 'plugin.js' because those may be filenames\n// used with other loaders (rpc loader) and are too generic\n// omegga.main.js is rather unique and helps avoid collision\nconst MAIN_FILE = 'omegga.main.js';\n\n// Documentation file (contains name, description, author, command helptext)\nconst DOC_FILE = 'doc.json';\nconst PLUGIN_FILE = 'plugin.json';\n\nexport default class NodePlugin extends Plugin {\n // every node plugin requires the main file and a doc file\n // may evolve this so it checks the contents of the doc file later\n static canLoad(pluginPath: string) {\n return (\n fs.existsSync(path.join(pluginPath, MAIN_FILE)) &&\n fs.existsSync(path.join(pluginPath, DOC_FILE))\n );\n }\n\n // unsafe node plugins (can potentially crash omegga) are powerful\n static getFormat() {\n return 'node_unsafe';\n }\n\n constructor(pluginPath: string, omegga: Omegga) {\n super(pluginPath, omegga);\n // TODO: validate documentation\n this.documentation = Plugin.readJSON(path.join(pluginPath, DOC_FILE));\n this.pluginConfig = Plugin.readJSON(path.join(pluginPath, PLUGIN_FILE));\n this.pluginFile = path.join(pluginPath, MAIN_FILE);\n\n // list of registered comands\n this.commands = [];\n }\n\n // documentation is based on doc.json file\n getDocumentation() {\n return this.documentation;\n }\n\n // loaded state is based on if the loadedPlugin object is created\n isLoaded() {\n return !!this.loadedPlugin;\n }\n\n // determing if a command is registered\n isCommand(cmd: string) {\n return this.commands.includes(cmd);\n }\n\n // require the plugin into the system, run the init func\n async load() {\n const stopPlugin = (reason?: string) => {\n Logger.errorp('error launching node plugin', this.getName(), ':', reason);\n try {\n this.disrequireAll();\n } catch (e) {\n Logger.errorp('error unloading node plugin (2)', this.getName(), e);\n }\n this.emitStatus();\n return false;\n };\n this.commands = [];\n\n try {\n const config = await this.storage.getConfig();\n if (this.pluginConfig?.emitConfig) {\n await fs.promises.writeFile(\n path.join(this.path, this.pluginConfig.emitConfig),\n JSON.stringify(config),\n );\n }\n\n // require the plugin itself\n const Plugin: OmeggaPlugin = require(this.pluginFile);\n\n // node plugins must export a class with a constructor\n if (\n typeof (Plugin as any).prototype !== 'object' ||\n typeof (Plugin as any).prototype.constructor !== 'function'\n )\n return stopPlugin('missing constructor in plugin');\n\n // interface with plugin store\n const store: PluginStore = {\n get: key => this.storage.get(key),\n set: (key, value) => this.storage.set(key, value),\n delete: key => this.storage.delete(key),\n wipe: () => this.storage.wipe(),\n count: () => this.storage.count(),\n keys: () => this.storage.keys(),\n };\n\n // create the loaded plugin\n this.loadedPlugin = new (Plugin as any)(this.omegga, config, store);\n\n // start the loaded plugin\n if (typeof this.loadedPlugin.init === 'function') {\n const result = await this.loadedPlugin.init();\n\n // plugins can return a result object\n if (typeof result === 'object' && result) {\n // if registeredCommands is in the results, register the provided strings as commands\n const cmds = result.registeredCommands;\n if (\n cmds &&\n cmds instanceof Array &&\n cmds.every(i => typeof i === 'string')\n )\n this.commands = cmds;\n }\n }\n\n this.emitStatus();\n return true;\n } catch (e) {\n Logger.errorp('error loading node plugin', this.getName(), e);\n this.emitStatus();\n return false;\n }\n }\n\n // disrequire the plugin into the system, run the stop func\n async unload() {\n // can't unload the plugin if it hasn't been loaded\n if (typeof this.loadedPlugin === 'undefined') {\n this.emitStatus();\n return false;\n }\n\n try {\n // run the stop func on the plugin if applicable\n if (typeof this.loadedPlugin.stop === 'function')\n await this.loadedPlugin.stop();\n\n // unload the plugin\n this.disrequireAll();\n this.loadedPlugin = undefined;\n this.emitStatus();\n this.commands = [];\n return true;\n } catch (e) {\n Logger.errorp('error unloading node plugin', this.getName(), e);\n this.emitStatus();\n return false;\n }\n }\n\n // forward plugin events to the loaded plugin instance\n async emitPlugin(ev: string, from: string, args: any[]) {\n if (typeof this.loadedPlugin?.pluginEvent === 'function') {\n return await this.loadedPlugin.pluginEvent(ev, from, ...args);\n }\n }\n\n // disrequire all that match plugin path in require.cache\n disrequireAll() {\n // get all files in plugin directory from require cache\n const requiredFiles = Object.keys(require.cache).filter(requiredFile =>\n requiredFile.includes(this.path),\n );\n // disrequire all the files\n requiredFiles.forEach(file => {\n try {\n disrequire(file);\n } catch (e) {\n if (e.code !== 'MODULE_NOT_FOUND')\n // ignore error thrown if a module was deleted\n throw e;\n }\n });\n }\n}\n"],"names":["util","Plugin","Logger"],"mappings":"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"}
@@ -29,6 +29,7 @@ class Omegga extends wrapper.default {
29
29
  this.started = false;
30
30
  this.starting = false;
31
31
  this.stopping = false;
32
+ this.crashDetected = false;
32
33
  this.verbose = logger.default.VERBOSE;
33
34
  logger.default.verbose("Running omegga", `v${version.VERSION}`.green);
34
35
  logger.default.verbose("Versions", process.versions);
@@ -85,12 +86,45 @@ class Omegga extends wrapper.default {
85
86
  this.writeln("Chat.MessageForUnknownCommands 0");
86
87
  this.restoreServer();
87
88
  });
89
+ const crashHandler = (line) => {
90
+ if (!this.crashDetected && (/Engine crash handling finished; re-raising signal \d+ for the default handler\. Good bye\./.test(
91
+ line
92
+ ) || /LogCore: === Critical error: ===/.test(line))) {
93
+ logger.default.error("Engine crash detected!");
94
+ this.crashDetected = true;
95
+ }
96
+ };
97
+ this.on("err", crashHandler);
98
+ this.on("line", crashHandler);
88
99
  this.on("exit", () => {
89
100
  this.stop();
90
101
  });
91
102
  this.on("closed", () => {
103
+ const wasCrash = this.crashDetected;
104
+ this.crashDetected = false;
92
105
  if (this.started) this.emit("exit");
93
- if (!this.stopping) this.stop();
106
+ const doRestart = async () => {
107
+ if (!wasCrash) return;
108
+ try {
109
+ const config = await this.webserver?.database?.getAutoRestartConfig();
110
+ if (config?.crashRestartEnabled) {
111
+ logger.default.logp("Restarting server after crash...");
112
+ this.webserver?.database?.addChatLog(
113
+ "server",
114
+ {},
115
+ "Server crashed, restarting..."
116
+ );
117
+ await this.start();
118
+ }
119
+ } catch (err) {
120
+ logger.default.error("Error restarting after crash", err);
121
+ }
122
+ };
123
+ if (!this.stopping) {
124
+ this.stop().then(doRestart);
125
+ } else {
126
+ this.once("server:stopped", () => doRestart());
127
+ }
94
128
  });
95
129
  this.on("cmd", (cmd, name) => {
96
130
  if (!default_commands.default.includes(cmd) && (!this.pluginLoader || !this.pluginLoader.isCommand(cmd))) {