@rpgjs/client 5.0.0-alpha.24 → 5.0.0-alpha.25
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.
- package/dist/{index30.js → Game/AnimationManager.js} +1 -1
- package/dist/Game/AnimationManager.js.map +1 -0
- package/dist/{index24.js → Game/Event.js} +2 -2
- package/dist/Game/Event.js.map +1 -0
- package/dist/{index29.js → Game/Map.js} +6 -6
- package/dist/Game/Map.js.map +1 -0
- package/dist/{index22.js → Game/Object.js} +4 -4
- package/dist/Game/Object.js.map +1 -0
- package/dist/{index23.js → Game/Player.js} +2 -2
- package/dist/Game/Player.js.map +1 -0
- package/dist/{index9.js → Gui/Gui.js} +10 -10
- package/dist/{index9.js.map → Gui/Gui.js.map} +1 -1
- package/dist/{index19.js → Resource.js} +1 -1
- package/dist/Resource.js.map +1 -0
- package/dist/RpgClientEngine.d.ts +31 -0
- package/dist/{index2.js → RpgClientEngine.js} +150 -18
- package/dist/RpgClientEngine.js.map +1 -0
- package/dist/{index18.js → Sound.js} +1 -1
- package/dist/Sound.js.map +1 -0
- package/dist/{index34.js → components/animations/animation.ce.js} +3 -3
- package/dist/components/animations/animation.ce.js.map +1 -0
- package/dist/{index33.js → components/animations/hit.ce.js} +1 -1
- package/dist/components/animations/hit.ce.js.map +1 -0
- package/dist/{index12.js → components/animations/index.js} +3 -3
- package/dist/components/animations/index.js.map +1 -0
- package/dist/{index17.js → components/character.ce.js} +4 -4
- package/dist/components/character.ce.js.map +1 -0
- package/dist/{index51.js → components/dynamics/parse-value.js} +1 -1
- package/dist/components/dynamics/parse-value.js.map +1 -0
- package/dist/{index39.js → components/dynamics/text.ce.js} +2 -2
- package/dist/components/dynamics/text.ce.js.map +1 -0
- package/dist/{index11.js → components/gui/box.ce.js} +8 -8
- package/dist/components/gui/box.ce.js.map +1 -0
- package/dist/{index10.js → components/gui/dialogbox/index.ce.js} +4 -4
- package/dist/components/gui/dialogbox/index.ce.js.map +1 -0
- package/dist/{index52.js → components/gui/dialogbox/itemMenu.ce.js} +1 -1
- package/dist/components/gui/dialogbox/itemMenu.ce.js.map +1 -0
- package/dist/{index48.js → components/gui/dialogbox/selection.ce.js} +4 -4
- package/dist/components/gui/dialogbox/selection.ce.js.map +1 -0
- package/dist/{index25.js → components/gui/mobile/index.js} +4 -4
- package/dist/components/gui/mobile/index.js.map +1 -0
- package/dist/{index40.js → components/gui/mobile/mobile.ce.js} +2 -2
- package/dist/components/gui/mobile/mobile.ce.js.map +1 -0
- package/dist/{index13.js → components/prebuilt/hp-bar.ce.js} +1 -1
- package/dist/components/prebuilt/hp-bar.ce.js.map +1 -0
- package/dist/{index14.js → components/prebuilt/light-halo.ce.js} +1 -1
- package/dist/components/prebuilt/light-halo.ce.js.map +1 -0
- package/dist/{index26.js → components/scenes/canvas.ce.js} +5 -5
- package/dist/components/scenes/canvas.ce.js.map +1 -0
- package/dist/{index43.js → components/scenes/draw-map.ce.js} +3 -3
- package/dist/components/scenes/draw-map.ce.js.map +1 -0
- package/dist/{index16.js → components/scenes/event-layer.ce.js} +4 -4
- package/dist/components/scenes/event-layer.ce.js.map +1 -0
- package/dist/{index6.js → core/inject.js} +2 -2
- package/dist/core/inject.js.map +1 -0
- package/dist/{index5.js → core/setup.js} +4 -4
- package/dist/core/setup.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +25 -24
- package/dist/index.js.map +1 -1
- package/dist/{index8.js → module.js} +4 -4
- package/dist/{index8.js.map → module.js.map} +1 -1
- package/dist/{index20.js → node_modules/.pnpm/@signe_di@2.6.0/node_modules/@signe/di/dist/index.js} +1 -1
- package/dist/node_modules/.pnpm/@signe_di@2.6.0/node_modules/@signe/di/dist/index.js.map +1 -0
- package/dist/{index42.js → node_modules/.pnpm/@signe_reactive@2.6.0/node_modules/@signe/reactive/dist/index.js} +1 -1
- package/dist/node_modules/.pnpm/@signe_reactive@2.6.0/node_modules/@signe/reactive/dist/index.js.map +1 -0
- package/dist/{index31.js → node_modules/.pnpm/@signe_room@2.6.0/node_modules/@signe/room/dist/index.js} +29 -30
- package/dist/node_modules/.pnpm/@signe_room@2.6.0/node_modules/@signe/room/dist/index.js.map +1 -0
- package/dist/{index41.js → node_modules/.pnpm/@signe_sync@2.6.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js} +1 -1
- package/dist/node_modules/.pnpm/@signe_sync@2.6.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +1 -0
- package/dist/{index32.js → node_modules/.pnpm/@signe_sync@2.6.0/node_modules/@signe/sync/dist/client/index.js} +5 -5
- package/dist/node_modules/.pnpm/@signe_sync@2.6.0/node_modules/@signe/sync/dist/client/index.js.map +1 -0
- package/dist/{index28.js → node_modules/.pnpm/@signe_sync@2.6.0/node_modules/@signe/sync/dist/index.js} +3 -3
- package/dist/node_modules/.pnpm/@signe_sync@2.6.0/node_modules/@signe/sync/dist/index.js.map +1 -0
- package/dist/{index44.js → node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js} +1 -1
- package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +1 -0
- package/dist/{index49.js → node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js} +2 -15
- package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -0
- package/dist/{index50.js → node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js} +2 -5
- package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -0
- package/dist/{index47.js → node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js} +813 -100
- package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -0
- package/dist/{index35.js → presets/animation.js} +1 -1
- package/dist/presets/animation.js.map +1 -0
- package/dist/{index38.js → presets/faceset.js} +1 -1
- package/dist/presets/faceset.js.map +1 -0
- package/dist/presets/index.js +14 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/{index36.js → presets/lpc.js} +1 -1
- package/dist/presets/lpc.js.map +1 -0
- package/dist/{index37.js → presets/rmspritesheet.js} +1 -1
- package/dist/presets/rmspritesheet.js.map +1 -0
- package/dist/{index27.js → services/AbstractSocket.js} +1 -1
- package/dist/services/AbstractSocket.js.map +1 -0
- package/dist/{index21.js → services/keyboardControls.js} +1 -1
- package/dist/services/keyboardControls.js.map +1 -0
- package/dist/{index7.js → services/loadMap.js} +2 -2
- package/dist/services/loadMap.js.map +1 -0
- package/dist/{index4.js → services/mmorpg.js} +6 -6
- package/dist/services/mmorpg.js.map +1 -0
- package/dist/services/standalone.d.ts +3 -0
- package/dist/{index3.js → services/standalone.js} +18 -12
- package/dist/services/standalone.js.map +1 -0
- package/package.json +5 -5
- package/src/RpgClientEngine.ts +193 -7
- package/src/index.ts +2 -1
- package/src/services/standalone.ts +16 -7
- package/vite.config.ts +4 -2
- package/dist/index10.js.map +0 -1
- package/dist/index11.js.map +0 -1
- package/dist/index12.js.map +0 -1
- package/dist/index13.js.map +0 -1
- package/dist/index14.js.map +0 -1
- package/dist/index15.js +0 -14
- package/dist/index15.js.map +0 -1
- package/dist/index16.js.map +0 -1
- package/dist/index17.js.map +0 -1
- package/dist/index18.js.map +0 -1
- package/dist/index19.js.map +0 -1
- package/dist/index2.js.map +0 -1
- package/dist/index20.js.map +0 -1
- package/dist/index21.js.map +0 -1
- package/dist/index22.js.map +0 -1
- package/dist/index23.js.map +0 -1
- package/dist/index24.js.map +0 -1
- package/dist/index25.js.map +0 -1
- package/dist/index26.js.map +0 -1
- package/dist/index27.js.map +0 -1
- package/dist/index28.js.map +0 -1
- package/dist/index29.js.map +0 -1
- package/dist/index3.js.map +0 -1
- package/dist/index30.js.map +0 -1
- package/dist/index31.js.map +0 -1
- package/dist/index32.js.map +0 -1
- package/dist/index33.js.map +0 -1
- package/dist/index34.js.map +0 -1
- package/dist/index35.js.map +0 -1
- package/dist/index36.js.map +0 -1
- package/dist/index37.js.map +0 -1
- package/dist/index38.js.map +0 -1
- package/dist/index39.js.map +0 -1
- package/dist/index4.js.map +0 -1
- package/dist/index40.js.map +0 -1
- package/dist/index41.js.map +0 -1
- package/dist/index42.js.map +0 -1
- package/dist/index43.js.map +0 -1
- package/dist/index44.js.map +0 -1
- package/dist/index45.js +0 -7
- package/dist/index45.js.map +0 -1
- package/dist/index46.js +0 -329
- package/dist/index46.js.map +0 -1
- package/dist/index47.js.map +0 -1
- package/dist/index48.js.map +0 -1
- package/dist/index49.js.map +0 -1
- package/dist/index5.js.map +0 -1
- package/dist/index50.js.map +0 -1
- package/dist/index51.js.map +0 -1
- package/dist/index52.js.map +0 -1
- package/dist/index53.js +0 -6
- package/dist/index53.js.map +0 -1
- package/dist/index54.js +0 -12
- package/dist/index54.js.map +0 -1
- package/dist/index55.js +0 -113
- package/dist/index55.js.map +0 -1
- package/dist/index56.js +0 -136
- package/dist/index56.js.map +0 -1
- package/dist/index57.js +0 -137
- package/dist/index57.js.map +0 -1
- package/dist/index58.js +0 -112
- package/dist/index58.js.map +0 -1
- package/dist/index59.js +0 -9
- package/dist/index59.js.map +0 -1
- package/dist/index6.js.map +0 -1
- package/dist/index7.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animation.js","sources":["../../src/presets/animation.ts"],"sourcesContent":["/**\n * Creates an animation spritesheet preset with automatic frame generation\n * \n * This function generates animation frames based on the provided width and height dimensions.\n * It creates a sequence of frames that progresses through the spritesheet from left to right,\n * top to bottom, with each frame having a 10ms time increment.\n * \n * @param {number} framesWidth - The number of frames horizontally in the spritesheet\n * @param {number} framesHeight - The number of frames vertically in the spritesheet\n * @returns {Object} Animation preset configuration object\n * \n * @example\n * ```javascript\n * // For a 4x4 spritesheet\n * const preset = AnimationSpritesheetPreset(4, 4);\n * // This will generate 16 frames with coordinates from (0,0) to (3,3)\n * ```\n */\nexport const AnimationSpritesheetPreset = (framesWidth: number, framesHeight: number) => {\n \n const animations: Array<{ time: number; frameX: number; frameY: number }> = [];\n\n for (let y = 0; y < framesHeight; y++) {\n for (let x = 0; x < framesWidth; x++) {\n const frameIndex = y * framesWidth + x;\n animations.push({ \n time: frameIndex * 10, \n frameX: x, \n frameY: y \n });\n }\n }\n \n return {\n framesWidth,\n framesHeight,\n textures: {\n default: {\n animations: () => [\n animations\n ],\n }\n }\n };\n};\n "],"names":[],"mappings":"AAkBO,MAAM,0BAAA,GAA6B,CAAC,WAAA,EAAqB,YAAA,KAAyB;AAErF,EAAA,MAAM,aAAsE,EAAC;AAE7E,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,YAAA,EAAc,CAAA,EAAA,EAAK;AACnC,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,WAAA,EAAa,CAAA,EAAA,EAAK;AAClC,MAAA,MAAM,UAAA,GAAa,IAAI,WAAA,GAAc,CAAA;AACrC,MAAA,UAAA,CAAW,IAAA,CAAK;AAAA,QACZ,MAAM,UAAA,GAAa,EAAA;AAAA,QACnB,MAAA,EAAQ,CAAA;AAAA,QACR,MAAA,EAAQ;AAAA,OACX,CAAA;AAAA,IACL;AAAA,EACJ;AAEA,EAAA,OAAO;AAAA,IACH,WAAA;AAAA,IACA,YAAA;AAAA,IACA,QAAA,EAAU;AAAA,MACN,OAAA,EAAS;AAAA,QACL,YAAY,MAAM;AAAA,UACd;AAAA;AACJ;AACJ;AACJ,GACJ;AACJ;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"faceset.js","sources":["../../src/presets/faceset.ts"],"sourcesContent":["/**\n * Creates a faceset preset for character expressions\n * \n * This preset allows you to define multiple facial expressions for a character,\n * where each expression corresponds to a specific frame position (frameX, frameY)\n * within a single faceset texture. Each expression is defined by its position\n * in the faceset grid.\n * \n * @param options - Object containing the faceset configuration\n * @param framesWidth - Number of frames horizontally in the faceset texture\n * @param framesHeight - Number of frames vertically in the faceset texture\n * @param expressions - Object mapping expression names to their frame positions as tuples [frameX, frameY]\n * @returns Faceset configuration with animations for each expression\n * \n * @example\n * ```typescript\n * const faceset = FacesetPreset({\n * id: \"facesetId\",\n * image: \"faceset.png\",\n * width: 1024,\n * height: 1024,\n * }, 4, 2, {\n * happy: [0, 0],\n * sad: [1, 0],\n * angry: [2, 0],\n * surprised: [3, 0]\n * });\n * ```\n */\nexport const FacesetPreset = (\n options: any,\n framesWidth: number, \n framesHeight: number,\n expressions: Record<string, [number, number]>,\n) => {\n \n const textures: Record<string, any> = {};\n \n // Create texture configuration for each expression\n Object.keys(expressions).forEach((expressionName) => {\n const [frameX, frameY] = expressions[expressionName];\n textures[expressionName] = {\n animations: () => [\n [{ \n time: 0, \n frameX: frameX, \n frameY: frameY \n }]\n ],\n };\n });\n \n return {\n ...options,\n framesWidth,\n framesHeight,\n textures\n };\n};\n "],"names":[],"mappings":"AA6BO,MAAM,aAAA,GAAgB,CACzB,OAAA,EACA,WAAA,EACA,cACA,WAAA,KACC;AAED,EAAA,MAAM,WAAgC,EAAC;AAGvC,EAAA,MAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAAE,OAAA,CAAQ,CAAC,cAAA,KAAmB;AACjD,IAAA,MAAM,CAAC,MAAA,EAAQ,MAAM,CAAA,GAAI,YAAY,cAAc,CAAA;AACnD,IAAA,QAAA,CAAS,cAAc,CAAA,GAAI;AAAA,MACvB,YAAY,MAAM;AAAA,QACd,CAAC;AAAA,UACG,IAAA,EAAM,CAAA;AAAA,UACN,MAAA;AAAA,UACA;AAAA,SACH;AAAA;AACL,KACJ;AAAA,EACJ,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACH,GAAG,OAAA;AAAA,IACH,WAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACJ;AACJ;;;;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AnimationSpritesheetPreset } from './animation.js';
|
|
2
|
+
import { LPCSpritesheetPreset } from './lpc.js';
|
|
3
|
+
import { RMSpritesheet } from './rmspritesheet.js';
|
|
4
|
+
import { FacesetPreset } from './faceset.js';
|
|
5
|
+
|
|
6
|
+
const Presets = {
|
|
7
|
+
RMSpritesheet,
|
|
8
|
+
LPCSpritesheetPreset,
|
|
9
|
+
AnimationSpritesheetPreset,
|
|
10
|
+
FacesetPreset
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export { Presets };
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/presets/index.ts"],"sourcesContent":["import { AnimationSpritesheetPreset } from \"./animation\";\nimport { LPCSpritesheetPreset } from \"./lpc\";\nimport { RMSpritesheet } from \"./rmspritesheet\";\nimport { FacesetPreset } from \"./faceset\";\n\nexport const Presets = {\n RMSpritesheet,\n LPCSpritesheetPreset,\n AnimationSpritesheetPreset,\n FacesetPreset\n}"],"names":[],"mappings":";;;;;AAKO,MAAM,OAAA,GAAU;AAAA,EACnB,aAAA;AAAA,EACA,oBAAA;AAAA,EACA,0BAAA;AAAA,EACA;AACJ;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lpc.js","sources":["../../src/presets/lpc.ts"],"sourcesContent":["import { Animation, Direction } from \"@rpgjs/common\";\n\nexport const LPCSpritesheetPreset = (options: {\n id: string;\n imageSource: string;\n width: number;\n height: number;\n ratio?: number;\n }) => {\n const ratio = options.ratio ?? 1;\n\n const frameY = (direction: Direction) => {\n return {\n [Direction.Down]: 2,\n [Direction.Left]: 1,\n [Direction.Right]: 3,\n [Direction.Up]: 0,\n }[direction];\n };\n \n const stand = (direction: Direction) => [\n { time: 0, frameX: 0, frameY: frameY(direction) },\n ];\n const anim = (\n direction: Direction,\n framesWidth: number,\n speed: number = 5\n ) => {\n const array: any = [];\n for (let i = 0; i < framesWidth; i++) {\n array.push({ time: i * speed, frameX: i, frameY: frameY(direction) });\n }\n return array;\n };\n \n return {\n id: options.id,\n image: options.imageSource,\n width: options.width,\n height: options.height,\n opacity: 1,\n rectWidth: 64 * ratio,\n rectHeight: 64 * ratio,\n framesWidth: 6,\n framesHeight: 4,\n spriteRealSize: {\n width: 48 * ratio,\n height: 52 * ratio,\n },\n textures: {\n [Animation.Stand]: {\n offset: {\n x: 0,\n y: 512 * ratio,\n },\n animations: ({ direction }) => [stand(direction)],\n },\n [Animation.Walk]: {\n offset: {\n x: 0,\n y: 512 * ratio,\n },\n framesWidth: 9,\n framesHeight: 4,\n animations: ({ direction }) => [anim(direction, 9)],\n },\n [Animation.Attack]: {\n offset: {\n x: 0,\n y: 768 * ratio,\n },\n framesWidth: 6,\n framesHeight: 4,\n animations: ({ direction }) => [anim(direction, 6, 3)],\n },\n [Animation.Skill]: {\n framesWidth: 7,\n framesHeight: 4,\n animations: ({ direction }) => [anim(direction, 7, 3)],\n },\n attack2: {\n offset: {\n x: 0,\n y: 256 * ratio,\n },\n framesWidth: 7,\n framesHeight: 8,\n animations: ({ direction }) => [anim(direction, 7, 3)],\n },\n ...(options.height > 3000\n ? {\n attack3: {\n offset: {\n x: 0,\n y: 5568 - 288 * 4,\n },\n rectWidth: 288,\n rectHeight: 288,\n framesWidth: 6,\n framesHeight: 4,\n animations: ({ direction }) => [anim(direction, 6, 3)],\n },\n }\n : {}),\n },\n };\n };\n "],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rmspritesheet.js","sources":["../../src/presets/rmspritesheet.ts"],"sourcesContent":["import { Direction, Animation } from '@rpgjs/common'\n\nexport const RMSpritesheet = (framesWidth: number, framesHeight: number, frameStand: number = 1) => {\n\n if (framesWidth <= frameStand) {\n frameStand = framesWidth - 1\n }\n\n const frameY = direction => {\n const gap = Math.max(4 - framesHeight, 0)\n return {\n [Direction.Down]: 0,\n [Direction.Left]: Math.max(0, 1 - gap),\n [Direction.Right]: Math.max(0, 2 - gap),\n [Direction.Up]: Math.max(0, 3 - gap)\n }[direction]\n }\n\n const stand = (direction: number) => [{ time: 0, frameX: frameStand, frameY: frameY(direction) }]\n const walk = direction => {\n const array: any = []\n const durationFrame = 10\n for (let i = 0; i < framesWidth; i++) {\n array.push({ time: i * durationFrame, frameX: i, frameY: frameY(direction) })\n }\n array.push({ time: array[array.length - 1].time + durationFrame })\n return array\n }\n\n return {\n textures: {\n [Animation.Stand]: {\n animations: ({direction}) => [stand(direction)]\n },\n [Animation.Walk]: {\n animations: ({direction}) => [walk(direction)]\n }\n },\n framesHeight,\n framesWidth\n }\n}"],"names":[],"mappings":";;AAEO,MAAM,aAAA,GAAgB,CAAC,WAAA,EAAqB,YAAA,EAAsB,aAAqB,CAAA,KAAM;AAEhG,EAAA,IAAI,eAAe,UAAA,EAAY;AAC3B,IAAA,UAAA,GAAa,WAAA,GAAc,CAAA;AAAA,EAC/B;AAEA,EAAA,MAAM,SAAS,CAAA,SAAA,KAAa;AACxB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,cAAc,CAAC,CAAA;AACxC,IAAA,OAAO;AAAA,MACH,CAAC,SAAA,CAAU,IAAI,GAAG,CAAA;AAAA,MAClB,CAAC,UAAU,IAAI,GAAG,KAAK,GAAA,CAAI,CAAA,EAAG,IAAI,GAAG,CAAA;AAAA,MACrC,CAAC,UAAU,KAAK,GAAG,KAAK,GAAA,CAAI,CAAA,EAAG,IAAI,GAAG,CAAA;AAAA,MACtC,CAAC,UAAU,EAAE,GAAG,KAAK,GAAA,CAAI,CAAA,EAAG,IAAI,GAAG;AAAA,MACrC,SAAS,CAAA;AAAA,EACf,CAAA;AAEA,EAAA,MAAM,KAAA,GAAQ,CAAC,SAAA,KAAsB,CAAC,EAAE,IAAA,EAAM,CAAA,EAAG,MAAA,EAAQ,UAAA,EAAY,MAAA,EAAQ,MAAA,CAAO,SAAS,GAAG,CAAA;AAChG,EAAA,MAAM,OAAO,CAAA,SAAA,KAAa;AACtB,IAAA,MAAM,QAAa,EAAC;AACpB,IAAA,MAAM,aAAA,GAAgB,EAAA;AACtB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,WAAA,EAAa,CAAA,EAAA,EAAK;AAClC,MAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,CAAA,GAAI,aAAA,EAAe,MAAA,EAAQ,CAAA,EAAG,MAAA,EAAQ,MAAA,CAAO,SAAS,CAAA,EAAG,CAAA;AAAA,IAChF;AACA,IAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,KAAA,CAAM,KAAA,CAAM,SAAS,CAAC,CAAA,CAAE,IAAA,GAAO,aAAA,EAAe,CAAA;AACjE,IAAA,OAAO,KAAA;AAAA,EACX,CAAA;AAEA,EAAA,OAAO;AAAA,IACH,QAAA,EAAU;AAAA,MACN,CAAC,SAAA,CAAU,KAAK,GAAG;AAAA,QACf,UAAA,EAAY,CAAC,EAAC,SAAA,OAAe,CAAC,KAAA,CAAM,SAAS,CAAC;AAAA,OAClD;AAAA,MACA,CAAC,SAAA,CAAU,IAAI,GAAG;AAAA,QACd,UAAA,EAAY,CAAC,EAAC,SAAA,OAAe,CAAC,IAAA,CAAK,SAAS,CAAC;AAAA;AACjD,KACJ;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACJ;AACJ;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbstractSocket.js","sources":["../../src/services/AbstractSocket.ts"],"sourcesContent":["import { Context } from \"@signe/di\";\n\nexport const WebSocketToken = \"websocket\";\n\nexport abstract class AbstractWebsocket {\n constructor(protected context: Context) {}\n\n abstract connection(listeners?: (data: any) => void): Promise<void>;\n abstract emit(event: string, data: any): void;\n abstract on(event: string, callback: (data: any) => void): void;\n abstract off(event: string, callback: (data: any) => void): void;\n abstract updateProperties(params: { room: string, host?: string }): void;\n abstract reconnect(listeners?: (data: any) => void): void;\n}\n"],"names":[],"mappings":"AAEO,MAAM,cAAA,GAAiB;AAEvB,MAAe,iBAAA,CAAkB;AAAA,EACtC,YAAsB,OAAA,EAAkB;AAAlB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAAmB;AAQ3C;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboardControls.js","sources":["../../src/services/keyboardControls.ts"],"sourcesContent":["import { KeyboardControls } from \"canvasengine\";\n\nexport enum Control {\n Action = 'action',\n Attack = 'attack',\n Defense = 'defense',\n Skill = 'skill',\n Back = 'back',\n Up = 1,\n Down = 3,\n Right = 2,\n Left = 4\n}\n\nexport function provideKeyboardControls() {\n return {\n provide: 'KeyboardControls',\n useValue: null,\n };\n}"],"names":["Control"],"mappings":"AAEO,IAAK,OAAA,qBAAAA,QAAAA,KAAL;AACL,EAAAA,SAAA,QAAA,CAAA,GAAS,QAAA;AACT,EAAAA,SAAA,QAAA,CAAA,GAAS,QAAA;AACT,EAAAA,SAAA,SAAA,CAAA,GAAU,SAAA;AACV,EAAAA,SAAA,OAAA,CAAA,GAAQ,OAAA;AACR,EAAAA,SAAA,MAAA,CAAA,GAAO,MAAA;AACP,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,QAAK,CAAA,CAAA,GAAL,IAAA;AACA,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,UAAO,CAAA,CAAA,GAAP,MAAA;AACA,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,WAAQ,CAAA,CAAA,GAAR,OAAA;AACA,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,UAAO,CAAA,CAAA,GAAP,MAAA;AATU,EAAA,OAAAA,QAAAA;AAAA,CAAA,EAAA,OAAA,IAAA,EAAA;AAYL,SAAS,uBAAA,GAA0B;AACxC,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,kBAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACZ;AACF;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { inject } from '
|
|
1
|
+
import { inject } from '../node_modules/.pnpm/@signe_di@2.6.0/node_modules/@signe/di/dist/index.js';
|
|
2
2
|
import { UpdateMapToken } from '@rpgjs/common';
|
|
3
3
|
|
|
4
4
|
const LoadMapToken = "LoadMapToken";
|
|
@@ -36,4 +36,4 @@ function provideLoadMap(options) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export { LoadMapService, LoadMapToken, provideLoadMap };
|
|
39
|
-
//# sourceMappingURL=
|
|
39
|
+
//# sourceMappingURL=loadMap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadMap.js","sources":["../../src/services/loadMap.ts"],"sourcesContent":["import { Context, inject } from \"@signe/di\";\nimport { UpdateMapToken, UpdateMapService } from \"@rpgjs/common\";\n\nexport const LoadMapToken = 'LoadMapToken'\n\n/**\n * Represents the structure of map data that should be returned by the load map callback.\n * This interface defines all the properties that can be provided when loading a custom map.\n * \n * @interface MapData\n */\ntype MapData = {\n /** Raw map data that will be passed to the map component */\n data: any;\n /** CanvasEngine component that will render the map */\n component: any;\n /** Optional map width in pixels, used for viewport calculations */\n width?: number;\n /** Optional map height in pixels, used for viewport calculations */\n height?: number;\n /** Optional map events data (NPCs, interactive objects, etc.) */\n events?: any;\n /** Optional map identifier, defaults to the mapId parameter if not provided */\n id?: string;\n}\n\n/**\n * Callback function type for loading map data.\n * This function receives a map ID and should return either a MapData object directly\n * or a Promise that resolves to a MapData object.\n * \n * @callback LoadMapOptions\n * @param {string} mapId - The identifier of the map to load\n * @returns {Promise<MapData> | MapData} The map data object or a promise resolving to it\n */\nexport type LoadMapOptions = (mapId: string) => Promise<MapData> | MapData \n\nexport class LoadMapService {\n private updateMapService: UpdateMapService;\n\n constructor(private context: Context, private options: LoadMapOptions) {\n if (context['side'] === 'server') {\n return\n }\n this.updateMapService = inject(context, UpdateMapToken);\n }\n\n async load(mapId: string) {\n const map = await this.options(mapId.replace('map-', ''))\n await this.updateMapService.update(map);\n return map;\n }\n}\n\n/**\n * Creates a dependency injection configuration for custom map loading on the client side.\n * \n * This function allows you to customize how maps are loaded and displayed by providing\n * a callback that defines custom map data and rendering components. It's designed to work\n * with the RPG-JS dependency injection system and enables integration of custom map formats\n * like Tiled TMX files or any other map data structure.\n * \n * The function sets up the necessary service providers for map loading, including:\n * - UpdateMapToken: Handles map updates in the client context\n * - LoadMapToken: Provides the LoadMapService with your custom loading logic\n * \n * **Design Concept:**\n * The function follows the provider pattern, creating a modular way to inject custom\n * map loading behavior into the RPG-JS client engine. It separates the concern of\n * map data fetching from map rendering, allowing developers to focus on their specific\n * map format while leveraging the engine's rendering capabilities.\n * \n * @param {LoadMapOptions} options - Callback function that handles map loading logic\n * @returns {Array<Object>} Array of dependency injection provider configurations\n * \n * @example\n * ```typescript\n * import { provideLoadMap } from '@rpgjs/client'\n * import { createModule } from '@rpgjs/common'\n * import MyTiledMapComponent from './MyTiledMapComponent.ce'\n * \n * // Basic usage with JSON map data\n * export function provideCustomMap() {\n * return createModule(\"CustomMap\", [\n * provideLoadMap(async (mapId) => {\n * const response = await fetch(`/maps/${mapId}.json`)\n * const mapData = await response.json()\n * \n * return {\n * data: mapData,\n * component: MyTiledMapComponent,\n * width: mapData.width,\n * height: mapData.height,\n * events: mapData.events\n * }\n * })\n * ])\n * }\n * \n * // Advanced usage with Tiled TMX files\n * export function provideTiledMap() {\n * return createModule(\"TiledMap\", [\n * provideLoadMap(async (mapId) => {\n * // Load TMX file\n * const tmxResponse = await fetch(`/tiled/${mapId}.tmx`)\n * const tmxData = await tmxResponse.text()\n * \n * // Parse TMX data (using a TMX parser)\n * const parsedMap = parseTMX(tmxData)\n * \n * return {\n * data: parsedMap,\n * component: TiledMapRenderer,\n * width: parsedMap.width * parsedMap.tilewidth,\n * height: parsedMap.height * parsedMap.tileheight,\n * events: parsedMap.objectGroups?.find(g => g.name === 'events')?.objects\n * }\n * })\n * ])\n * }\n * \n * // Synchronous usage for static maps\n * export function provideStaticMap() {\n * return createModule(\"StaticMap\", [\n * provideLoadMap((mapId) => {\n * const staticMaps = {\n * 'town': { tiles: [...], npcs: [...] },\n * 'dungeon': { tiles: [...], monsters: [...] }\n * }\n * \n * return {\n * data: staticMaps[mapId],\n * component: StaticMapComponent,\n * width: 800,\n * height: 600\n * }\n * })\n * ])\n * }\n * ```\n * \n * @since 4.0.0\n * @see {@link LoadMapOptions} for callback function signature\n * @see {@link MapData} for return data structure\n */\nexport function provideLoadMap(options: LoadMapOptions) {\n return [\n {\n provide: UpdateMapToken,\n useFactory: (context: Context) => {\n if (context['side'] === 'client') {\n console.warn('UpdateMapToken is not overridden')\n }\n return\n },\n },\n {\n provide: LoadMapToken,\n useFactory: (context: Context) => new LoadMapService(context, options),\n },\n ];\n}\n"],"names":[],"mappings":";;;AAGO,MAAM,YAAA,GAAe;AAkCrB,MAAM,cAAA,CAAe;AAAA,EAG1B,WAAA,CAAoB,SAA0B,OAAA,EAAyB;AAAnD,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAA0B,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAC5C,IAAA,IAAI,OAAA,CAAQ,MAAM,CAAA,KAAM,QAAA,EAAU;AAChC,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,gBAAA,GAAmB,MAAA,CAAO,OAAA,EAAS,cAAc,CAAA;AAAA,EACxD;AAAA,EAEA,MAAM,KAAK,KAAA,EAAe;AACxB,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA,CAAQ,MAAM,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAC,CAAA;AACxD,IAAA,MAAM,IAAA,CAAK,gBAAA,CAAiB,MAAA,CAAO,GAAG,CAAA;AACtC,IAAA,OAAO,GAAA;AAAA,EACT;AACF;AA6FO,SAAS,eAAe,OAAA,EAAyB;AACtD,EAAA,OAAO;AAAA,IACL;AAAA,MACE,OAAA,EAAS,cAAA;AAAA,MACT,UAAA,EAAY,CAAC,OAAA,KAAqB;AAChC,QAAA,IAAI,OAAA,CAAQ,MAAM,CAAA,KAAM,QAAA,EAAU;AAChC,UAAA,OAAA,CAAQ,KAAK,kCAAkC,CAAA;AAAA,QACjD;AACA,QAAA;AAAA,MACF;AAAA,KACF;AAAA,IACA;AAAA,MACE,OAAA,EAAS,YAAA;AAAA,MACT,YAAY,CAAC,OAAA,KAAqB,IAAI,cAAA,CAAe,SAAS,OAAO;AAAA;AACvE,GACF;AACF;;;;"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { connectionRoom } from '
|
|
2
|
-
import { RpgGui } from '
|
|
3
|
-
import { RpgClientEngine } from '
|
|
4
|
-
import { WebSocketToken, AbstractWebsocket } from './
|
|
1
|
+
import { connectionRoom } from '../node_modules/.pnpm/@signe_sync@2.6.0/node_modules/@signe/sync/dist/client/index.js';
|
|
2
|
+
import { RpgGui } from '../Gui/Gui.js';
|
|
3
|
+
import { RpgClientEngine } from '../RpgClientEngine.js';
|
|
4
|
+
import { WebSocketToken, AbstractWebsocket } from './AbstractSocket.js';
|
|
5
5
|
import { UpdateMapToken, UpdateMapService } from '@rpgjs/common';
|
|
6
|
-
import { provideKeyboardControls } from './
|
|
6
|
+
import { provideKeyboardControls } from './keyboardControls.js';
|
|
7
7
|
|
|
8
8
|
class BridgeWebsocket extends AbstractWebsocket {
|
|
9
9
|
constructor(context, options = {}) {
|
|
@@ -71,4 +71,4 @@ function provideMmorpg(options) {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
export { provideMmorpg };
|
|
74
|
-
//# sourceMappingURL=
|
|
74
|
+
//# sourceMappingURL=mmorpg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mmorpg.js","sources":["../../src/services/mmorpg.ts"],"sourcesContent":["import { Context } from \"@signe/di\";\nimport { connectionRoom } from \"@signe/sync/client\";\nimport { RpgGui } from \"../Gui/Gui\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\nimport { AbstractWebsocket, WebSocketToken } from \"./AbstractSocket\";\nimport { UpdateMapService, UpdateMapToken } from \"@rpgjs/common\";\nimport { provideKeyboardControls } from \"./keyboardControls\";\n\ninterface MmorpgOptions {\n host?: string;\n}\n\nclass BridgeWebsocket extends AbstractWebsocket {\n private socket: any;\n private privateId: string;\n\n constructor(protected context: Context, private options: MmorpgOptions = {}) {\n super(context);\n const id = localStorage.getItem(\"rpgjs-user-id\") || crypto.randomUUID()\n localStorage.setItem(\"rpgjs-user-id\", id)\n this.privateId = id\n }\n\n async connection(listeners?: (data: any) => void) {\n // tmp\n class Room {\n \n }\n const instance = new Room()\n this.socket = await connectionRoom({\n host: this.options.host || window.location.host,\n room: \"lobby-1\",\n id: this.privateId\n }, instance)\n\n listeners?.(this.socket)\n }\n\n on(key: string, callback: (data: any) => void) {\n this.socket.on(key, callback);\n }\n\n off(event: string, callback: (data: any) => void) {\n this.socket.off(event, callback);\n }\n\n emit(event: string, data: any) {\n this.socket.emit(event, data);\n }\n\n updateProperties({ room }: { room: any }) {\n this.socket.conn.updateProperties({\n room: room,\n id: this.privateId,\n host: this.options.host\n })\n }\n\n async reconnect(listeners?: (data: any) => void) {\n this.socket.conn.reconnect()\n }\n}\n\nclass UpdateMapStandaloneService extends UpdateMapService {\n constructor(protected context: Context, private options: MmorpgOptions) {\n super(context);\n }\n\n async update(map: any) {\n // nothing\n }\n}\n\nexport function provideMmorpg(options: MmorpgOptions) {\n return [\n {\n provide: WebSocketToken,\n useFactory: (context: Context) => new BridgeWebsocket(context, options),\n },\n {\n provide: UpdateMapToken,\n useFactory: (context: Context) => new UpdateMapStandaloneService(context, options),\n },\n provideKeyboardControls(),\n RpgGui,\n RpgClientEngine,\n ];\n}\n"],"names":[],"mappings":";;;;;;;AAYA,MAAM,wBAAwB,iBAAA,CAAkB;AAAA,EAI9C,WAAA,CAAsB,OAAA,EAA0B,OAAA,GAAyB,EAAC,EAAG;AAC3E,IAAA,KAAA,CAAM,OAAO,CAAA;AADO,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAA0B,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAE9C,IAAA,MAAM,KAAK,YAAA,CAAa,OAAA,CAAQ,eAAe,CAAA,IAAK,OAAO,UAAA,EAAW;AACtE,IAAA,YAAA,CAAa,OAAA,CAAQ,iBAAiB,EAAE,CAAA;AACxC,IAAA,IAAA,CAAK,SAAA,GAAY,EAAA;AAAA,EACnB;AAAA,EAEA,MAAM,WAAW,SAAA,EAAiC;AAAA,IAEhD,MAAM,IAAA,CAAK;AAAA;AAGX,IAAA,MAAM,QAAA,GAAW,IAAI,IAAA,EAAK;AAC1B,IAAA,IAAA,CAAK,MAAA,GAAS,MAAM,cAAA,CAAe;AAAA,MAC/B,IAAA,EAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,IAAQ,OAAO,QAAA,CAAS,IAAA;AAAA,MAC3C,IAAA,EAAM,SAAA;AAAA,MACN,IAAI,IAAA,CAAK;AAAA,OACV,QAAQ,CAAA;AAEX,IAAA,SAAA,GAAY,KAAK,MAAM,CAAA;AAAA,EACzB;AAAA,EAEA,EAAA,CAAG,KAAa,QAAA,EAA+B;AAC7C,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,GAAA,EAAK,QAAQ,CAAA;AAAA,EAC9B;AAAA,EAEA,GAAA,CAAI,OAAe,QAAA,EAA+B;AAChD,IAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAA,EAAO,QAAQ,CAAA;AAAA,EACjC;AAAA,EAEA,IAAA,CAAK,OAAe,IAAA,EAAW;AAC7B,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,KAAA,EAAO,IAAI,CAAA;AAAA,EAC9B;AAAA,EAEA,gBAAA,CAAiB,EAAE,IAAA,EAAK,EAAkB;AACxC,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,gBAAA,CAAiB;AAAA,MAChC,IAAA;AAAA,MACA,IAAI,IAAA,CAAK,SAAA;AAAA,MACT,IAAA,EAAM,KAAK,OAAA,CAAQ;AAAA,KACpB,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,UAAU,SAAA,EAAiC;AAChD,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,SAAA,EAAU;AAAA,EAC5B;AACF;AAEA,MAAM,mCAAmC,gBAAA,CAAiB;AAAA,EACxD,WAAA,CAAsB,SAA0B,OAAA,EAAwB;AACtE,IAAA,KAAA,CAAM,OAAO,CAAA;AADO,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAA0B,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAEhD;AAAA,EAEA,MAAM,OAAO,GAAA,EAAU;AAAA,EAEvB;AACF;AAEO,SAAS,cAAc,OAAA,EAAwB;AACpD,EAAA,OAAO;AAAA,IACL;AAAA,MACE,OAAA,EAAS,cAAA;AAAA,MACT,YAAY,CAAC,OAAA,KAAqB,IAAI,eAAA,CAAgB,SAAS,OAAO;AAAA,KACxE;AAAA,IACA;AAAA,MACE,OAAA,EAAS,cAAA;AAAA,MACT,YAAY,CAAC,OAAA,KAAqB,IAAI,0BAAA,CAA2B,SAAS,OAAO;AAAA,KACnF;AAAA,IACA,uBAAA,EAAwB;AAAA,IACxB,MAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
|
|
@@ -9,6 +9,7 @@ declare class BridgeWebsocket extends AbstractWebsocket {
|
|
|
9
9
|
private room;
|
|
10
10
|
private socket;
|
|
11
11
|
private rooms;
|
|
12
|
+
private serverInstance;
|
|
12
13
|
constructor(context: Context, server: any);
|
|
13
14
|
connection(listeners?: (data: any) => void): Promise<any>;
|
|
14
15
|
private _connection;
|
|
@@ -52,6 +53,8 @@ declare class BridgeWebsocket extends AbstractWebsocket {
|
|
|
52
53
|
* ```
|
|
53
54
|
*/
|
|
54
55
|
reconnect(listeners?: (data: any) => void): Promise<void>;
|
|
56
|
+
getServer(): any;
|
|
57
|
+
getSocket(): any;
|
|
55
58
|
}
|
|
56
59
|
declare class UpdateMapStandaloneService extends UpdateMapService {
|
|
57
60
|
private server;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { WebSocketToken, AbstractWebsocket } from './
|
|
2
|
-
import { ServerIo, ClientIo } from '
|
|
3
|
-
import { RpgClientEngine } from '
|
|
1
|
+
import { WebSocketToken, AbstractWebsocket } from './AbstractSocket.js';
|
|
2
|
+
import { ServerIo, ClientIo } from '../node_modules/.pnpm/@signe_room@2.6.0/node_modules/@signe/room/dist/index.js';
|
|
3
|
+
import { RpgClientEngine } from '../RpgClientEngine.js';
|
|
4
4
|
import { UpdateMapToken, UpdateMapService } from '@rpgjs/common';
|
|
5
|
-
import { RpgGui } from '
|
|
6
|
-
import { provideKeyboardControls } from './
|
|
5
|
+
import { RpgGui } from '../Gui/Gui.js';
|
|
6
|
+
import { provideKeyboardControls } from './keyboardControls.js';
|
|
7
7
|
|
|
8
8
|
class BridgeWebsocket extends AbstractWebsocket {
|
|
9
9
|
constructor(context, server) {
|
|
@@ -22,14 +22,14 @@ class BridgeWebsocket extends AbstractWebsocket {
|
|
|
22
22
|
this.room = new ServerIo("lobby-1", this.rooms);
|
|
23
23
|
}
|
|
24
24
|
async connection(listeners) {
|
|
25
|
-
|
|
26
|
-
await
|
|
27
|
-
this.context.set("server",
|
|
25
|
+
this.serverInstance = new this.server(this.room);
|
|
26
|
+
await this.serverInstance.onStart();
|
|
27
|
+
this.context.set("server", this.serverInstance);
|
|
28
28
|
return this._connection(listeners);
|
|
29
29
|
}
|
|
30
30
|
async _connection(listeners) {
|
|
31
|
-
|
|
32
|
-
this.socket = new ClientIo(
|
|
31
|
+
this.serverInstance = this.context.get("server");
|
|
32
|
+
this.socket = new ClientIo(this.serverInstance, "player-client-id");
|
|
33
33
|
const url = new URL("http://localhost");
|
|
34
34
|
const request = new Request(url.toString(), {
|
|
35
35
|
method: "GET",
|
|
@@ -38,7 +38,7 @@ class BridgeWebsocket extends AbstractWebsocket {
|
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
listeners?.(this.socket);
|
|
41
|
-
await
|
|
41
|
+
await this.serverInstance.onConnect(this.socket.conn, { request });
|
|
42
42
|
this.room.clients.set(this.socket.id, this.socket);
|
|
43
43
|
return this.socket;
|
|
44
44
|
}
|
|
@@ -99,6 +99,12 @@ class BridgeWebsocket extends AbstractWebsocket {
|
|
|
99
99
|
listeners?.(socket);
|
|
100
100
|
});
|
|
101
101
|
}
|
|
102
|
+
getServer() {
|
|
103
|
+
return this.serverInstance;
|
|
104
|
+
}
|
|
105
|
+
getSocket() {
|
|
106
|
+
return this.socket;
|
|
107
|
+
}
|
|
102
108
|
}
|
|
103
109
|
class UpdateMapStandaloneService extends UpdateMapService {
|
|
104
110
|
/**
|
|
@@ -146,4 +152,4 @@ function provideRpg(server) {
|
|
|
146
152
|
}
|
|
147
153
|
|
|
148
154
|
export { provideRpg };
|
|
149
|
-
//# sourceMappingURL=
|
|
155
|
+
//# sourceMappingURL=standalone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standalone.js","sources":["../../src/services/standalone.ts"],"sourcesContent":["import { AbstractWebsocket, WebSocketToken } from \"./AbstractSocket\";\nimport { ClientIo, ServerIo } from \"@signe/room\";\nimport { Context } from \"@signe/di\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\nimport { UpdateMapService, UpdateMapToken } from \"@rpgjs/common\";\nimport { LoadMapToken } from \"./loadMap\";\nimport { RpgGui } from \"../Gui/Gui\";\nimport { provideKeyboardControls } from \"./keyboardControls\";\n\ntype ServerIo = any;\ntype ClientIo = any;\n\nclass BridgeWebsocket extends AbstractWebsocket {\n private room: ServerIo;\n private socket: ClientIo;\n private rooms = {\n partyFn: async (roomId: string) => {\n this.room = new ServerIo(roomId, this.rooms);\n const server = new this.server(this.room)\n await server.onStart();\n this.context.set('server', server)\n return server\n } \n }\n private serverInstance: any;\n\n constructor(protected context: Context, private server: any) {\n super(context);\n // fake room\n this.room = new ServerIo(\"lobby-1\", this.rooms);\n }\n\n async connection(listeners?: (data: any) => void) {\n this.serverInstance = new this.server(this.room);\n await this.serverInstance.onStart();\n this.context.set('server', this.serverInstance)\n return this._connection(listeners)\n }\n\n private async _connection(listeners?: (data: any) => void) {\n this.serverInstance = this.context.get('server')\n this.socket = new ClientIo(this.serverInstance, 'player-client-id');\n const url = new URL('http://localhost')\n const request = new Request(url.toString(), {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n }\n })\n listeners?.(this.socket)\n await this.serverInstance.onConnect(this.socket.conn as any, { request } as any);\n this.room.clients.set(this.socket.id, this.socket);\n return this.socket\n }\n\n on(key: string, callback: (data: any) => void) {\n this.socket.addEventListener(\"message\", (event) => {\n const object = JSON.parse(event);\n if (object.type === key) {\n callback(object.value);\n }\n });\n }\n\n off(event: string, callback: (data: any) => void) {\n this.socket.removeEventListener(event, callback);\n }\n\n emit(event: string, data: any) {\n this.socket.send({\n action: event,\n value: data,\n });\n }\n\n /**\n * Update underlying connection properties before a reconnect\n *\n * Design\n * - Dynamically register a factory for the requested room to ensure a fresh server instance\n * - Swap the internal ServerIo to target the new room\n *\n * @param params - Properties to update\n * @param params.room - The target room id (e.g. `map-simplemap2`)\n *\n * @example\n * ```ts\n * websocket.updateProperties({ room: 'map-simplemap2' })\n * await websocket.reconnect()\n * ```\n */\n updateProperties({ room }: { room: any }) {\n // empty\n }\n\n /**\n * Reconnect the client to the current Party room\n *\n * Design\n * - Must be called after `updateProperties()` when switching rooms\n * - Rebuilds the client <-> server bridge and re-triggers connection listeners\n *\n * @param listeners - Optional callback to re-bind event handlers on the new socket\n *\n * @example\n * ```ts\n * websocket.updateProperties({ room: 'map-dungeon' })\n * await websocket.reconnect((socket) => {\n * // re-bind events here\n * })\n * ```\n */\n async reconnect(listeners?: (data: any) => void) {\n await this._connection((socket) => {\n listeners?.(socket)\n })\n }\n\n getServer() {\n return this.serverInstance\n }\n\n getSocket() {\n return this.socket\n }\n}\n\nclass UpdateMapStandaloneService extends UpdateMapService {\n private server: any;\n\n /**\n * Update the current room map data on the server side\n *\n * Design\n * - Uses the in-memory server instance stored in context (standalone mode)\n * - Builds a local HTTP-like request to the current Party room endpoint\n *\n * @param map - The map payload to apply on the server\n *\n * @example\n * ```ts\n * await updateMapService.update({ width: 1024, height: 768, events: [] })\n * ```\n */\n async update(map: any) {\n this.server = this.context.get('server')\n const roomId = this.server?.room?.id ?? 'lobby-1'\n const req = {\n url: `http://localhost/parties/main/${roomId}/map/update`,\n method: 'POST',\n headers: new Headers({}),\n json: async () => {\n return map;\n }\n };\n await this.server.onRequest(req)\n }\n}\n\nexport function provideRpg(server: any) {\n return [\n {\n provide: WebSocketToken,\n useFactory: (context: Context) => new BridgeWebsocket(context, server),\n },\n {\n provide: UpdateMapToken,\n useClass: UpdateMapStandaloneService,\n },\n provideKeyboardControls(),\n RpgGui,\n RpgClientEngine,\n ];\n}"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpgjs/client",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.25",
|
|
4
4
|
"description": "RPGJS is a framework for creating RPG/MMORPG games",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
"pixi.js": "^8.9.2"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@rpgjs/client": "5.0.0-alpha.
|
|
26
|
-
"@rpgjs/common": "5.0.0-alpha.
|
|
27
|
-
"@rpgjs/server": "5.0.0-alpha.
|
|
25
|
+
"@rpgjs/client": "5.0.0-alpha.25",
|
|
26
|
+
"@rpgjs/common": "5.0.0-alpha.25",
|
|
27
|
+
"@rpgjs/server": "5.0.0-alpha.25",
|
|
28
28
|
"@signe/di": "^2.6.0",
|
|
29
29
|
"@signe/room": "^2.6.0",
|
|
30
30
|
"@signe/sync": "^2.6.0",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"rxjs": "^7.8.2"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@canvasengine/compiler": "2.0.0-beta.
|
|
35
|
+
"@canvasengine/compiler": "2.0.0-beta.41",
|
|
36
36
|
"vite": "^7.2.7",
|
|
37
37
|
"vite-plugin-dts": "^4.5.4",
|
|
38
38
|
"vitest": "^4.0.15"
|
package/src/RpgClientEngine.ts
CHANGED
|
@@ -45,6 +45,8 @@ export class RpgClientEngine<T = any> {
|
|
|
45
45
|
}
|
|
46
46
|
renderer: PIXI.Renderer;
|
|
47
47
|
tick: Observable<number>;
|
|
48
|
+
private canvasApp?: any;
|
|
49
|
+
private canvasElement?: any;
|
|
48
50
|
playerIdSignal = signal<string | null>(null);
|
|
49
51
|
spriteComponentsBehind = signal<any[]>([]);
|
|
50
52
|
spriteComponentsInFront = signal<any[]>([]);
|
|
@@ -71,6 +73,10 @@ export class RpgClientEngine<T = any> {
|
|
|
71
73
|
private playersReceived$ = new BehaviorSubject<boolean>(false);
|
|
72
74
|
private eventsReceived$ = new BehaviorSubject<boolean>(false);
|
|
73
75
|
private onAfterLoadingSubscription?: any;
|
|
76
|
+
|
|
77
|
+
// Store subscriptions and event listeners for cleanup
|
|
78
|
+
private tickSubscriptions: any[] = [];
|
|
79
|
+
private resizeHandler?: () => void;
|
|
74
80
|
|
|
75
81
|
constructor(public context) {
|
|
76
82
|
this.webSocket = inject(WebSocketToken);
|
|
@@ -140,7 +146,7 @@ export class RpgClientEngine<T = any> {
|
|
|
140
146
|
...currentValues,
|
|
141
147
|
values: new Map([['__default__', controlInstance]])
|
|
142
148
|
}
|
|
143
|
-
this.controlsReady.set(
|
|
149
|
+
this.controlsReady.set(undefined);
|
|
144
150
|
}
|
|
145
151
|
|
|
146
152
|
async start() {
|
|
@@ -148,16 +154,19 @@ export class RpgClientEngine<T = any> {
|
|
|
148
154
|
this.selector = document.body.querySelector("#rpg") as HTMLElement;
|
|
149
155
|
|
|
150
156
|
const { app, canvasElement } = await bootstrapCanvas(this.selector, Canvas);
|
|
157
|
+
this.canvasApp = app;
|
|
158
|
+
this.canvasElement = canvasElement;
|
|
151
159
|
this.renderer = app.renderer as PIXI.Renderer;
|
|
152
160
|
this.tick = canvasElement?.propObservables?.context['tick'].observable
|
|
153
161
|
|
|
154
|
-
this.tick.subscribe(() => {
|
|
162
|
+
const inputCheckSubscription = this.tick.subscribe(() => {
|
|
155
163
|
if (Date.now() - this.lastInputTime > 100) {
|
|
156
164
|
const player = this.getCurrentPlayer();
|
|
157
165
|
if (!player) return;
|
|
158
166
|
(this.sceneMap as any).stopMovement(player);
|
|
159
167
|
}
|
|
160
|
-
})
|
|
168
|
+
});
|
|
169
|
+
this.tickSubscriptions.push(inputCheckSubscription);
|
|
161
170
|
|
|
162
171
|
|
|
163
172
|
this.hooks.callHooks("client-spritesheets-load", this).subscribe();
|
|
@@ -175,11 +184,12 @@ export class RpgClientEngine<T = any> {
|
|
|
175
184
|
await lastValueFrom(this.hooks.callHooks("client-engine-onStart", this));
|
|
176
185
|
|
|
177
186
|
// wondow is resize
|
|
178
|
-
|
|
187
|
+
this.resizeHandler = () => {
|
|
179
188
|
this.hooks.callHooks("client-engine-onWindowResize", this).subscribe();
|
|
180
|
-
}
|
|
189
|
+
};
|
|
190
|
+
window.addEventListener('resize', this.resizeHandler);
|
|
181
191
|
|
|
182
|
-
this.tick.subscribe((tick) => {
|
|
192
|
+
const tickSubscription = this.tick.subscribe((tick) => {
|
|
183
193
|
this.hooks.callHooks("client-engine-onStep", this, tick).subscribe();
|
|
184
194
|
|
|
185
195
|
// Clean up old prediction states and input history every 60 ticks (approximately every second at 60fps)
|
|
@@ -188,7 +198,8 @@ export class RpgClientEngine<T = any> {
|
|
|
188
198
|
this.prediction?.cleanup(now);
|
|
189
199
|
this.prediction?.tryApplyPendingSnapshot();
|
|
190
200
|
}
|
|
191
|
-
})
|
|
201
|
+
});
|
|
202
|
+
this.tickSubscriptions.push(tickSubscription);
|
|
192
203
|
|
|
193
204
|
await this.webSocket.connection(() => {
|
|
194
205
|
this.initListeners()
|
|
@@ -1294,4 +1305,179 @@ export class RpgClientEngine<T = any> {
|
|
|
1294
1305
|
private async replayUnackedInputsFromFrame(_startFrame: number): Promise<void> {
|
|
1295
1306
|
// Prediction controller handles replay internally. Kept for backwards compatibility.
|
|
1296
1307
|
}
|
|
1308
|
+
|
|
1309
|
+
/**
|
|
1310
|
+
* Clear all client resources and reset state
|
|
1311
|
+
*
|
|
1312
|
+
* This method should be called to clean up all client-side resources when
|
|
1313
|
+
* shutting down or resetting the client engine. It:
|
|
1314
|
+
* - Destroys the PIXI renderer
|
|
1315
|
+
* - Stops all sounds
|
|
1316
|
+
* - Cleans up subscriptions and event listeners
|
|
1317
|
+
* - Resets scene map
|
|
1318
|
+
* - Stops ping/pong interval
|
|
1319
|
+
* - Clears prediction states
|
|
1320
|
+
*
|
|
1321
|
+
* ## Design
|
|
1322
|
+
*
|
|
1323
|
+
* This method is used primarily in testing environments to ensure clean
|
|
1324
|
+
* state between tests. In production, the client engine typically persists
|
|
1325
|
+
* for the lifetime of the application.
|
|
1326
|
+
*
|
|
1327
|
+
* @example
|
|
1328
|
+
* ```ts
|
|
1329
|
+
* // In test cleanup
|
|
1330
|
+
* afterEach(() => {
|
|
1331
|
+
* clientEngine.clear();
|
|
1332
|
+
* });
|
|
1333
|
+
* ```
|
|
1334
|
+
*/
|
|
1335
|
+
clear(): void {
|
|
1336
|
+
try {
|
|
1337
|
+
// First, unsubscribe from all tick subscriptions to stop rendering attempts
|
|
1338
|
+
for (const subscription of this.tickSubscriptions) {
|
|
1339
|
+
if (subscription && typeof subscription.unsubscribe === 'function') {
|
|
1340
|
+
subscription.unsubscribe();
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
this.tickSubscriptions = [];
|
|
1344
|
+
|
|
1345
|
+
// Stop ping/pong interval
|
|
1346
|
+
if (this.pingInterval) {
|
|
1347
|
+
clearInterval(this.pingInterval);
|
|
1348
|
+
this.pingInterval = null;
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
// Clean up onAfterLoading subscription
|
|
1352
|
+
if (this.onAfterLoadingSubscription && typeof this.onAfterLoadingSubscription.unsubscribe === 'function') {
|
|
1353
|
+
this.onAfterLoadingSubscription.unsubscribe();
|
|
1354
|
+
this.onAfterLoadingSubscription = undefined;
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
// Clean up canvasElement (CanvasEngine) BEFORE destroying PIXI app
|
|
1358
|
+
// This prevents CanvasEngine from trying to render after PIXI is destroyed
|
|
1359
|
+
// CanvasEngine manages its own render loop which could try to access PIXI after destruction
|
|
1360
|
+
if (this.canvasElement) {
|
|
1361
|
+
try {
|
|
1362
|
+
// Try to stop or cleanup canvasElement if it has cleanup methods
|
|
1363
|
+
if (typeof (this.canvasElement as any).destroy === 'function') {
|
|
1364
|
+
(this.canvasElement as any).destroy();
|
|
1365
|
+
}
|
|
1366
|
+
// Clear the reference
|
|
1367
|
+
this.canvasElement = undefined;
|
|
1368
|
+
} catch (error) {
|
|
1369
|
+
// Ignore errors during canvasElement cleanup
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
// Reset scene map if it exists (this should stop any ongoing animations/renders)
|
|
1374
|
+
if (this.sceneMap && typeof (this.sceneMap as any).reset === 'function') {
|
|
1375
|
+
(this.sceneMap as any).reset();
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
// Stop all sounds
|
|
1379
|
+
this.stopAllSounds();
|
|
1380
|
+
|
|
1381
|
+
// Remove resize event listener
|
|
1382
|
+
if (this.resizeHandler && typeof window !== 'undefined') {
|
|
1383
|
+
window.removeEventListener('resize', this.resizeHandler);
|
|
1384
|
+
this.resizeHandler = undefined;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
// Destroy PIXI app and renderer if they exist
|
|
1388
|
+
// Destroy the app first, which will destroy the renderer
|
|
1389
|
+
// Store renderer reference before destroying app (since app.destroy() will destroy the renderer)
|
|
1390
|
+
const rendererStillExists = this.renderer && typeof this.renderer.destroy === 'function';
|
|
1391
|
+
|
|
1392
|
+
if (this.canvasApp && typeof this.canvasApp.destroy === 'function') {
|
|
1393
|
+
try {
|
|
1394
|
+
// Stop the ticker first to prevent any render calls during destruction
|
|
1395
|
+
if (this.canvasApp.ticker) {
|
|
1396
|
+
if (typeof this.canvasApp.ticker.stop === 'function') {
|
|
1397
|
+
this.canvasApp.ticker.stop();
|
|
1398
|
+
}
|
|
1399
|
+
// Also remove all listeners from ticker to prevent callbacks
|
|
1400
|
+
if (typeof this.canvasApp.ticker.removeAll === 'function') {
|
|
1401
|
+
this.canvasApp.ticker.removeAll();
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
// Stop the renderer's ticker if it exists separately
|
|
1406
|
+
if (this.renderer && (this.renderer as any).ticker) {
|
|
1407
|
+
if (typeof (this.renderer as any).ticker.stop === 'function') {
|
|
1408
|
+
(this.renderer as any).ticker.stop();
|
|
1409
|
+
}
|
|
1410
|
+
if (typeof (this.renderer as any).ticker.removeAll === 'function') {
|
|
1411
|
+
(this.renderer as any).ticker.removeAll();
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
// Remove the canvas from DOM before destroying to prevent render attempts
|
|
1416
|
+
if (this.canvasApp.canvas && this.canvasApp.canvas.parentNode) {
|
|
1417
|
+
this.canvasApp.canvas.parentNode.removeChild(this.canvasApp.canvas);
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
// Destroy with minimal options to avoid issues
|
|
1421
|
+
// Don't pass options that might trigger additional cleanup that could fail
|
|
1422
|
+
this.canvasApp.destroy(true);
|
|
1423
|
+
} catch (error) {
|
|
1424
|
+
// Ignore errors during destruction
|
|
1425
|
+
}
|
|
1426
|
+
this.canvasApp = undefined;
|
|
1427
|
+
// canvasApp.destroy() already destroyed the renderer, so just null it
|
|
1428
|
+
this.renderer = null as any;
|
|
1429
|
+
} else if (rendererStillExists) {
|
|
1430
|
+
// Fallback: destroy renderer directly only if app doesn't exist or wasn't destroyed
|
|
1431
|
+
try {
|
|
1432
|
+
// Stop the renderer's ticker if it has one
|
|
1433
|
+
if ((this.renderer as any).ticker) {
|
|
1434
|
+
if (typeof (this.renderer as any).ticker.stop === 'function') {
|
|
1435
|
+
(this.renderer as any).ticker.stop();
|
|
1436
|
+
}
|
|
1437
|
+
if (typeof (this.renderer as any).ticker.removeAll === 'function') {
|
|
1438
|
+
(this.renderer as any).ticker.removeAll();
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
this.renderer.destroy(true);
|
|
1443
|
+
} catch (error) {
|
|
1444
|
+
// Ignore errors during destruction
|
|
1445
|
+
}
|
|
1446
|
+
this.renderer = null as any;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
// Clean up prediction controller
|
|
1450
|
+
if (this.prediction) {
|
|
1451
|
+
// Prediction controller cleanup is handled internally when destroyed
|
|
1452
|
+
this.prediction = undefined;
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
// Reset signals
|
|
1456
|
+
this.playerIdSignal.set(null);
|
|
1457
|
+
this.cameraFollowTargetId.set(null);
|
|
1458
|
+
this.spriteComponentsBehind.set([]);
|
|
1459
|
+
this.spriteComponentsInFront.set([]);
|
|
1460
|
+
|
|
1461
|
+
// Clear maps and arrays
|
|
1462
|
+
this.spritesheets.clear();
|
|
1463
|
+
this.sounds.clear();
|
|
1464
|
+
this.componentAnimations = [];
|
|
1465
|
+
this.particleSettings.emitters = [];
|
|
1466
|
+
|
|
1467
|
+
// Reset state
|
|
1468
|
+
this.stopProcessingInput = false;
|
|
1469
|
+
this.lastInputTime = 0;
|
|
1470
|
+
this.inputFrameCounter = 0;
|
|
1471
|
+
this.frameOffset = 0;
|
|
1472
|
+
this.rtt = 0;
|
|
1473
|
+
|
|
1474
|
+
// Reset behavior subjects
|
|
1475
|
+
this.mapLoadCompleted$.next(false);
|
|
1476
|
+
this.playerIdReceived$.next(false);
|
|
1477
|
+
this.playersReceived$.next(false);
|
|
1478
|
+
this.eventsReceived$.next(false);
|
|
1479
|
+
} catch (error) {
|
|
1480
|
+
console.warn('Error during client engine cleanup:', error);
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1297
1483
|
}
|
package/src/index.ts
CHANGED
|
@@ -21,4 +21,5 @@ export { Control } from "./services/keyboardControls";
|
|
|
21
21
|
export { RpgClientObject } from "./Game/Object";
|
|
22
22
|
export { RpgClientPlayer } from "./Game/Player";
|
|
23
23
|
export { RpgClientEvent } from "./Game/Event";
|
|
24
|
-
export { withMobile } from "./components/gui/mobile";
|
|
24
|
+
export { withMobile } from "./components/gui/mobile";
|
|
25
|
+
export * from "./services/AbstractSocket";
|
|
@@ -22,6 +22,7 @@ class BridgeWebsocket extends AbstractWebsocket {
|
|
|
22
22
|
return server
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
+
private serverInstance: any;
|
|
25
26
|
|
|
26
27
|
constructor(protected context: Context, private server: any) {
|
|
27
28
|
super(context);
|
|
@@ -30,15 +31,15 @@ class BridgeWebsocket extends AbstractWebsocket {
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
async connection(listeners?: (data: any) => void) {
|
|
33
|
-
|
|
34
|
-
await
|
|
35
|
-
this.context.set('server',
|
|
34
|
+
this.serverInstance = new this.server(this.room);
|
|
35
|
+
await this.serverInstance.onStart();
|
|
36
|
+
this.context.set('server', this.serverInstance)
|
|
36
37
|
return this._connection(listeners)
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
private async _connection(listeners?: (data: any) => void) {
|
|
40
|
-
|
|
41
|
-
this.socket = new ClientIo(
|
|
41
|
+
this.serverInstance = this.context.get('server')
|
|
42
|
+
this.socket = new ClientIo(this.serverInstance, 'player-client-id');
|
|
42
43
|
const url = new URL('http://localhost')
|
|
43
44
|
const request = new Request(url.toString(), {
|
|
44
45
|
method: 'GET',
|
|
@@ -47,7 +48,7 @@ class BridgeWebsocket extends AbstractWebsocket {
|
|
|
47
48
|
}
|
|
48
49
|
})
|
|
49
50
|
listeners?.(this.socket)
|
|
50
|
-
await
|
|
51
|
+
await this.serverInstance.onConnect(this.socket.conn as any, { request } as any);
|
|
51
52
|
this.room.clients.set(this.socket.id, this.socket);
|
|
52
53
|
return this.socket
|
|
53
54
|
}
|
|
@@ -114,6 +115,14 @@ class BridgeWebsocket extends AbstractWebsocket {
|
|
|
114
115
|
listeners?.(socket)
|
|
115
116
|
})
|
|
116
117
|
}
|
|
118
|
+
|
|
119
|
+
getServer() {
|
|
120
|
+
return this.serverInstance
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
getSocket() {
|
|
124
|
+
return this.socket
|
|
125
|
+
}
|
|
117
126
|
}
|
|
118
127
|
|
|
119
128
|
class UpdateMapStandaloneService extends UpdateMapService {
|
|
@@ -162,4 +171,4 @@ export function provideRpg(server: any) {
|
|
|
162
171
|
RpgGui,
|
|
163
172
|
RpgClientEngine,
|
|
164
173
|
];
|
|
165
|
-
}
|
|
174
|
+
}
|
package/vite.config.ts
CHANGED
|
@@ -19,9 +19,11 @@ export default defineConfig({
|
|
|
19
19
|
sourcemap: true,
|
|
20
20
|
minify: false,
|
|
21
21
|
lib: {
|
|
22
|
-
entry:
|
|
22
|
+
entry: {
|
|
23
|
+
index: 'src/index.ts'
|
|
24
|
+
},
|
|
23
25
|
formats: ['es'],
|
|
24
|
-
fileName:
|
|
26
|
+
fileName: (format, entryName) => `${entryName}.js`
|
|
25
27
|
},
|
|
26
28
|
rollupOptions: {
|
|
27
29
|
external: [/@rpgjs/, 'esbuild', 'canvasengine', '@canvasengine/presets', 'rxjs', 'pixi.js'],
|