@rpgjs/client 5.0.0-beta.5 → 5.0.0-beta.7

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 (133) hide show
  1. package/dist/Game/AnimationManager.d.ts +2 -2
  2. package/dist/Game/AnimationManager.js +18 -9
  3. package/dist/Game/AnimationManager.js.map +1 -1
  4. package/dist/Game/AnimationManager.spec.d.ts +1 -0
  5. package/dist/Game/Map.d.ts +7 -9
  6. package/dist/Game/Map.js +3 -3
  7. package/dist/Game/Map.js.map +1 -1
  8. package/dist/Game/Object.d.ts +28 -12
  9. package/dist/Game/Object.js +29 -4
  10. package/dist/Game/Object.js.map +1 -1
  11. package/dist/Gui/Gui.d.ts +2 -2
  12. package/dist/Gui/Gui.js +15 -15
  13. package/dist/Gui/Gui.js.map +1 -1
  14. package/dist/Gui/NotificationManager.d.ts +1 -1
  15. package/dist/Gui/NotificationManager.js.map +1 -1
  16. package/dist/Resource.js.map +1 -1
  17. package/dist/RpgClient.d.ts +22 -0
  18. package/dist/RpgClientEngine.d.ts +15 -12
  19. package/dist/RpgClientEngine.js +19 -4
  20. package/dist/RpgClientEngine.js.map +1 -1
  21. package/dist/Sound.js.map +1 -1
  22. package/dist/_virtual/{_@oxc-project_runtime@0.127.0 → _@oxc-project_runtime@0.128.0}/helpers/decorate.js +1 -1
  23. package/dist/_virtual/{_@oxc-project_runtime@0.127.0 → _@oxc-project_runtime@0.128.0}/helpers/decorateMetadata.js +1 -1
  24. package/dist/components/animations/animation.ce.js +2 -1
  25. package/dist/components/animations/animation.ce.js.map +1 -1
  26. package/dist/components/animations/hit.ce.js +2 -1
  27. package/dist/components/animations/hit.ce.js.map +1 -1
  28. package/dist/components/animations/index.js +4 -4
  29. package/dist/components/character.ce.js +57 -2
  30. package/dist/components/character.ce.js.map +1 -1
  31. package/dist/components/dynamics/parse-value.d.ts +1 -1
  32. package/dist/components/dynamics/parse-value.js.map +1 -1
  33. package/dist/components/dynamics/text.ce.js +2 -1
  34. package/dist/components/dynamics/text.ce.js.map +1 -1
  35. package/dist/components/gui/box.ce.js +2 -1
  36. package/dist/components/gui/box.ce.js.map +1 -1
  37. package/dist/components/gui/dialogbox/index.ce.js +2 -1
  38. package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
  39. package/dist/components/gui/gameover.ce.js +2 -1
  40. package/dist/components/gui/gameover.ce.js.map +1 -1
  41. package/dist/components/gui/hud/hud.ce.js +2 -1
  42. package/dist/components/gui/hud/hud.ce.js.map +1 -1
  43. package/dist/components/gui/menu/equip-menu.ce.js +2 -1
  44. package/dist/components/gui/menu/equip-menu.ce.js.map +1 -1
  45. package/dist/components/gui/menu/exit-menu.ce.js +2 -1
  46. package/dist/components/gui/menu/exit-menu.ce.js.map +1 -1
  47. package/dist/components/gui/menu/items-menu.ce.js +2 -1
  48. package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
  49. package/dist/components/gui/menu/main-menu.ce.js +14 -13
  50. package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
  51. package/dist/components/gui/menu/options-menu.ce.js +2 -1
  52. package/dist/components/gui/menu/options-menu.ce.js.map +1 -1
  53. package/dist/components/gui/menu/skills-menu.ce.js +2 -1
  54. package/dist/components/gui/menu/skills-menu.ce.js.map +1 -1
  55. package/dist/components/gui/mobile/index.d.ts +1 -1
  56. package/dist/components/gui/mobile/index.js +2 -2
  57. package/dist/components/gui/mobile/index.js.map +1 -1
  58. package/dist/components/gui/mobile/mobile.ce.js +2 -1
  59. package/dist/components/gui/mobile/mobile.ce.js.map +1 -1
  60. package/dist/components/gui/notification/notification.ce.js +9 -5
  61. package/dist/components/gui/notification/notification.ce.js.map +1 -1
  62. package/dist/components/gui/save-load.ce.js +2 -1
  63. package/dist/components/gui/save-load.ce.js.map +1 -1
  64. package/dist/components/gui/shop/shop.ce.js +2 -1
  65. package/dist/components/gui/shop/shop.ce.js.map +1 -1
  66. package/dist/components/gui/title-screen.ce.js +2 -1
  67. package/dist/components/gui/title-screen.ce.js.map +1 -1
  68. package/dist/components/prebuilt/hp-bar.ce.js +2 -1
  69. package/dist/components/prebuilt/hp-bar.ce.js.map +1 -1
  70. package/dist/components/prebuilt/light-halo.ce.js +2 -1
  71. package/dist/components/prebuilt/light-halo.ce.js.map +1 -1
  72. package/dist/components/scenes/canvas.ce.js +4 -3
  73. package/dist/components/scenes/canvas.ce.js.map +1 -1
  74. package/dist/components/scenes/draw-map.ce.js +2 -1
  75. package/dist/components/scenes/draw-map.ce.js.map +1 -1
  76. package/dist/components/scenes/event-layer.ce.js +5 -4
  77. package/dist/components/scenes/event-layer.ce.js.map +1 -1
  78. package/dist/core/inject.js +1 -1
  79. package/dist/core/inject.js.map +1 -1
  80. package/dist/core/setup.js +1 -1
  81. package/dist/core/setup.js.map +1 -1
  82. package/dist/index.js +20 -20
  83. package/dist/module.js +1 -1
  84. package/dist/module.js.map +1 -1
  85. package/dist/node_modules/.pnpm/{@signe_di@2.9.0 → @signe_di@2.10.0}/node_modules/@signe/di/dist/index.js +7 -117
  86. package/dist/node_modules/.pnpm/@signe_di@2.10.0/node_modules/@signe/di/dist/index.js.map +1 -0
  87. package/dist/node_modules/.pnpm/@signe_reactive@2.10.0/node_modules/@signe/reactive/dist/index.js +45 -0
  88. package/dist/node_modules/.pnpm/@signe_reactive@2.10.0/node_modules/@signe/reactive/dist/index.js.map +1 -0
  89. package/dist/node_modules/.pnpm/@signe_reactive@2.9.2/node_modules/@signe/reactive/dist/index.js +227 -0
  90. package/dist/node_modules/.pnpm/@signe_reactive@2.9.2/node_modules/@signe/reactive/dist/index.js.map +1 -0
  91. package/dist/node_modules/.pnpm/@signe_room@2.10.0/node_modules/@signe/room/dist/index.js +611 -0
  92. package/dist/node_modules/.pnpm/@signe_room@2.10.0/node_modules/@signe/room/dist/index.js.map +1 -0
  93. package/dist/node_modules/.pnpm/@signe_sync@2.10.0/node_modules/@signe/sync/dist/client/index.js +44 -0
  94. package/dist/node_modules/.pnpm/@signe_sync@2.10.0/node_modules/@signe/sync/dist/client/index.js.map +1 -0
  95. package/dist/node_modules/.pnpm/{@signe_sync@2.9.0 → @signe_sync@2.10.0}/node_modules/@signe/sync/dist/index.js +29 -136
  96. package/dist/node_modules/.pnpm/@signe_sync@2.10.0/node_modules/@signe/sync/dist/index.js.map +1 -0
  97. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -1
  98. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -1
  99. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -1
  100. package/dist/presets/animation.js.map +1 -1
  101. package/dist/presets/faceset.js.map +1 -1
  102. package/dist/presets/icon.js.map +1 -1
  103. package/dist/presets/lpc.js.map +1 -1
  104. package/dist/presets/rmspritesheet.js.map +1 -1
  105. package/dist/services/AbstractSocket.js.map +1 -1
  106. package/dist/services/keyboardControls.js.map +1 -1
  107. package/dist/services/loadMap.js +1 -1
  108. package/dist/services/loadMap.js.map +1 -1
  109. package/dist/services/mmorpg.js +1 -1
  110. package/dist/services/mmorpg.js.map +1 -1
  111. package/dist/services/save.js.map +1 -1
  112. package/dist/services/standalone.js +1 -1
  113. package/dist/services/standalone.js.map +1 -1
  114. package/dist/utils/getEntityProp.js.map +1 -1
  115. package/package.json +10 -10
  116. package/src/Game/AnimationManager.spec.ts +30 -0
  117. package/src/Game/AnimationManager.ts +22 -10
  118. package/src/Game/Object.ts +46 -8
  119. package/src/RpgClient.ts +27 -0
  120. package/src/RpgClientEngine.ts +18 -2
  121. package/src/components/character.ce +72 -0
  122. package/dist/node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js.map +0 -1
  123. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js +0 -463
  124. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js.map +0 -1
  125. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js +0 -2191
  126. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js.map +0 -1
  127. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js +0 -10
  128. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +0 -1
  129. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js +0 -91
  130. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js.map +0 -1
  131. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js.map +0 -1
  132. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js +0 -14
  133. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationManager.js","names":[],"sources":["../../src/Gui/NotificationManager.ts"],"sourcesContent":["import { signal, animatedSignal } from \"canvasengine\";\n\nexport type NotificationType = \"info\" | \"warn\" | \"error\";\n\nexport interface NotificationPayload {\n message: string;\n type?: NotificationType;\n icon?: string;\n time?: number;\n sound?: string;\n}\n\nexport interface NotificationItem extends NotificationPayload {\n id: number;\n opacity: any;\n offset: any;\n layoutY: any;\n removing: boolean;\n}\n\nconst DEFAULT_DURATION = 220;\n\nexport class NotificationManager {\n stack = signal<NotificationItem[]>([]);\n private _counter = 0;\n\n add(payload: NotificationPayload, engine?: { playSound?: (id: string) => void }) {\n const id = ++this._counter;\n const opacity = animatedSignal(0, { duration: DEFAULT_DURATION });\n const offset = animatedSignal(12, { duration: DEFAULT_DURATION });\n const layoutY = animatedSignal(0, { duration: DEFAULT_DURATION });\n const item: NotificationItem = {\n id,\n message: payload.message,\n type: payload.type || \"info\",\n icon: payload.icon,\n time: payload.time,\n sound: payload.sound,\n opacity,\n offset,\n layoutY,\n removing: false,\n };\n this.stack.update((list) => [...list, item]);\n opacity.set(1);\n offset.set(0);\n\n if (payload.sound && engine?.playSound) {\n engine.playSound(payload.sound);\n }\n\n const delay = typeof payload.time === \"number\" ? payload.time : 2000;\n setTimeout(() => {\n this.remove(id);\n }, delay);\n }\n\n remove(id: number) {\n const list = this.stack();\n const item = list.find((it) => it.id === id);\n if (!item || item.removing) return;\n item.removing = true;\n item.opacity.set(0);\n item.offset.set(-8);\n setTimeout(() => {\n this.stack.update((items) => items.filter((it) => it.id !== id));\n }, DEFAULT_DURATION);\n }\n}\n"],"mappings":";;AAoBA,IAAM,mBAAmB;AAEzB,IAAa,sBAAb,MAAiC;;eACvB,OAA2B,EAAE,CAAC;kBACnB;;CAEnB,IAAI,SAA8B,QAA+C;EAC/E,MAAM,KAAK,EAAE,KAAK;EAClB,MAAM,UAAU,eAAe,GAAG,EAAE,UAAU,kBAAkB,CAAC;EACjE,MAAM,SAAS,eAAe,IAAI,EAAE,UAAU,kBAAkB,CAAC;EACjE,MAAM,UAAU,eAAe,GAAG,EAAE,UAAU,kBAAkB,CAAC;EACjE,MAAM,OAAyB;GAC7B;GACA,SAAS,QAAQ;GACjB,MAAM,QAAQ,QAAQ;GACtB,MAAM,QAAQ;GACd,MAAM,QAAQ;GACd,OAAO,QAAQ;GACf;GACA;GACA;GACA,UAAU;GACX;AACD,OAAK,MAAM,QAAQ,SAAS,CAAC,GAAG,MAAM,KAAK,CAAC;AAC5C,UAAQ,IAAI,EAAE;AACd,SAAO,IAAI,EAAE;AAEb,MAAI,QAAQ,SAAS,QAAQ,UAC3B,QAAO,UAAU,QAAQ,MAAM;EAGjC,MAAM,QAAQ,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAChE,mBAAiB;AACf,QAAK,OAAO,GAAG;KACd,MAAM;;CAGX,OAAO,IAAY;EAEjB,MAAM,OADO,KAAK,OACL,CAAK,MAAM,OAAO,GAAG,OAAO,GAAG;AAC5C,MAAI,CAAC,QAAQ,KAAK,SAAU;AAC5B,OAAK,WAAW;AAChB,OAAK,QAAQ,IAAI,EAAE;AACnB,OAAK,OAAO,IAAI,GAAG;AACnB,mBAAiB;AACf,QAAK,MAAM,QAAQ,UAAU,MAAM,QAAQ,OAAO,GAAG,OAAO,GAAG,CAAC;KAC/D,iBAAiB"}
1
+ {"version":3,"file":"NotificationManager.js","names":[],"sources":["../../src/Gui/NotificationManager.ts"],"sourcesContent":["import { signal, animatedSignal } from \"canvasengine\";\n\nexport type NotificationType = \"info\" | \"warn\" | \"error\";\n\nexport interface NotificationPayload {\n message: string;\n type?: NotificationType;\n icon?: string;\n time?: number;\n sound?: string;\n}\n\nexport interface NotificationItem extends NotificationPayload {\n id: number;\n opacity: any;\n offset: any;\n layoutY: any;\n removing: boolean;\n}\n\nconst DEFAULT_DURATION = 220;\n\nexport class NotificationManager {\n stack = signal<NotificationItem[]>([]);\n private _counter = 0;\n\n add(payload: NotificationPayload, engine?: { playSound?: (id: string) => void }) {\n const id = ++this._counter;\n const opacity = animatedSignal(0, { duration: DEFAULT_DURATION });\n const offset = animatedSignal(12, { duration: DEFAULT_DURATION });\n const layoutY = animatedSignal(0, { duration: DEFAULT_DURATION });\n const item: NotificationItem = {\n id,\n message: payload.message,\n type: payload.type || \"info\",\n icon: payload.icon,\n time: payload.time,\n sound: payload.sound,\n opacity,\n offset,\n layoutY,\n removing: false,\n };\n this.stack.update((list) => [...list, item]);\n opacity.set(1);\n offset.set(0);\n\n if (payload.sound && engine?.playSound) {\n engine.playSound(payload.sound);\n }\n\n const delay = typeof payload.time === \"number\" ? payload.time : 2000;\n setTimeout(() => {\n this.remove(id);\n }, delay);\n }\n\n remove(id: number) {\n const list = this.stack();\n const item = list.find((it) => it.id === id);\n if (!item || item.removing) return;\n item.removing = true;\n item.opacity.set(0);\n item.offset.set(-8);\n setTimeout(() => {\n this.stack.update((items) => items.filter((it) => it.id !== id));\n }, DEFAULT_DURATION);\n }\n}\n"],"mappings":";;AAoBA,IAAM,mBAAmB;AAEzB,IAAa,sBAAb,MAAiC;;eACvB,OAA2B,EAAE,CAAC;kBACnB;;CAEnB,IAAI,SAA8B,QAA+C;EAC/E,MAAM,KAAK,EAAE,KAAK;EAClB,MAAM,UAAU,eAAe,GAAG,EAAE,UAAU,kBAAkB,CAAC;EACjE,MAAM,SAAS,eAAe,IAAI,EAAE,UAAU,kBAAkB,CAAC;EACjE,MAAM,UAAU,eAAe,GAAG,EAAE,UAAU,kBAAkB,CAAC;EACjE,MAAM,OAAyB;GAC7B;GACA,SAAS,QAAQ;GACjB,MAAM,QAAQ,QAAQ;GACtB,MAAM,QAAQ;GACd,MAAM,QAAQ;GACd,OAAO,QAAQ;GACf;GACA;GACA;GACA,UAAU;GACX;EACD,KAAK,MAAM,QAAQ,SAAS,CAAC,GAAG,MAAM,KAAK,CAAC;EAC5C,QAAQ,IAAI,EAAE;EACd,OAAO,IAAI,EAAE;EAEb,IAAI,QAAQ,SAAS,QAAQ,WAC3B,OAAO,UAAU,QAAQ,MAAM;EAGjC,MAAM,QAAQ,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;EAChE,iBAAiB;GACf,KAAK,OAAO,GAAG;KACd,MAAM;;CAGX,OAAO,IAAY;EAEjB,MAAM,OADO,KAAK,OACL,CAAK,MAAM,OAAO,GAAG,OAAO,GAAG;EAC5C,IAAI,CAAC,QAAQ,KAAK,UAAU;EAC5B,KAAK,WAAW;EAChB,KAAK,QAAQ,IAAI,EAAE;EACnB,KAAK,OAAO,IAAI,GAAG;EACnB,iBAAiB;GACf,KAAK,MAAM,QAAQ,UAAU,MAAM,QAAQ,OAAO,GAAG,OAAO,GAAG,CAAC;KAC/D,iBAAiB"}
@@ -1 +1 @@
1
- {"version":3,"file":"Resource.js","names":[],"sources":["../src/Resource.ts"],"sourcesContent":["import { RpgClientEngine } from './RpgClientEngine';\n\n/**\n * RpgResource class\n * \n * Provides a unified API to access resource file links (images and sounds) in the game.\n * Resources are stored as Maps of resource IDs to file paths/URLs.\n * \n * ## Design\n * \n * RpgResource acts as a facade over the engine's resource storage, providing\n * easy access to resource file links. It maintains Maps that are synchronized\n * with the engine's internal storage, but only stores the file paths/URLs,\n * not the full resource objects.\n * \n * @example\n * ```ts\n * import { RpgResource } from '@rpgjs/client'\n * \n * // Get spritesheet image link\n * const imageLink = RpgResource.spritesheets.get('hero')\n * \n * // Get sound file link\n * const soundLink = RpgResource.sounds.get('town-music')\n * \n * // Set a new resource link\n * RpgResource.spritesheets.set('new-sprite', './assets/new-sprite.png')\n * ```\n */\nexport class RpgResource {\n private static engine: RpgClientEngine | null = null;\n private static _spritesheets: Map<string, string> = new Map();\n private static _sounds: Map<string, string> = new Map();\n\n /**\n * Initialize RpgResource with the engine instance\n * \n * This is called automatically by the engine during initialization.\n * It synchronizes the resource Maps with the engine's internal storage.\n * \n * @param engine - The RpgClientEngine instance\n */\n static init(engine: RpgClientEngine): void {\n RpgResource.engine = engine;\n RpgResource.syncResources();\n }\n\n /**\n * Synchronize resource Maps with the engine's internal storage\n * \n * Extracts file links from spritesheets and sounds stored in the engine\n * and updates the Maps accordingly.\n * \n * @private\n */\n private static syncResources(): void {\n if (!RpgResource.engine) {\n return;\n }\n\n // Sync spritesheets\n RpgResource._spritesheets.clear();\n RpgResource.engine.spritesheets.forEach((spritesheet, id) => {\n // Extract image path from spritesheet\n const imageLink = spritesheet?.image || spritesheet?.imageSource || undefined;\n if (imageLink) {\n RpgResource._spritesheets.set(id, imageLink);\n }\n });\n\n // Sync sounds\n RpgResource._sounds.clear();\n RpgResource.engine.sounds.forEach((sound, id) => {\n // Extract src path from sound\n let soundLink: string | undefined;\n \n // If it's a Howler instance, try to get src from _src or src property\n if (sound && typeof sound === 'object') {\n if (sound._src && Array.isArray(sound._src) && sound._src.length > 0) {\n soundLink = sound._src[0];\n } else if (sound.src && typeof sound.src === 'string') {\n soundLink = sound.src;\n } else if (sound.src && Array.isArray(sound.src) && sound.src.length > 0) {\n soundLink = sound.src[0];\n }\n }\n \n if (soundLink) {\n RpgResource._sounds.set(id, soundLink);\n }\n });\n }\n\n /**\n * Get/Set image links for spritesheets\n * \n * Map of spritesheet IDs to their image file paths/URLs.\n * This Map is synchronized with the engine's spritesheet storage.\n * \n * @type {Map<string, string>}\n * \n * @example\n * ```ts\n * // Get an image link\n * const imageLink = RpgResource.spritesheets.get('hero')\n * \n * // Set a new image link\n * RpgResource.spritesheets.set('new-sprite', './assets/new-sprite.png')\n * \n * // Check if a spritesheet exists\n * if (RpgResource.spritesheets.has('monster')) {\n * const link = RpgResource.spritesheets.get('monster')\n * }\n * ```\n */\n static get spritesheets(): Map<string, string> {\n // Sync before returning to ensure we have the latest data\n RpgResource.syncResources();\n return RpgResource._spritesheets;\n }\n\n /**\n * Get/Set sound file links\n * \n * Map of sound IDs to their audio file paths/URLs.\n * This Map is synchronized with the engine's sound storage.\n * \n * @type {Map<string, string>}\n * \n * @example\n * ```ts\n * // Get a sound link\n * const soundLink = RpgResource.sounds.get('town-music')\n * \n * // Set a new sound link\n * RpgResource.sounds.set('new-sound', './assets/new-sound.ogg')\n * \n * // Iterate over all sounds\n * RpgResource.sounds.forEach((link, id) => {\n * console.log(`Sound ${id}: ${link}`)\n * })\n * ```\n */\n static get sounds(): Map<string, string> {\n // Sync before returning to ensure we have the latest data\n RpgResource.syncResources();\n return RpgResource._sounds;\n }\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,IAAa,cAAb,MAAa,YAAY;;gBACyB;;;uCACI,IAAI,KAAK;;;iCACf,IAAI,KAAK;;;;;;;;;;CAUvD,OAAO,KAAK,QAA+B;AACzC,cAAY,SAAS;AACrB,cAAY,eAAe;;;;;;;;;;CAW7B,OAAe,gBAAsB;AACnC,MAAI,CAAC,YAAY,OACf;AAIF,cAAY,cAAc,OAAO;AACjC,cAAY,OAAO,aAAa,SAAS,aAAa,OAAO;GAE3D,MAAM,YAAY,aAAa,SAAS,aAAa,eAAe,KAAA;AACpE,OAAI,UACF,aAAY,cAAc,IAAI,IAAI,UAAU;IAE9C;AAGF,cAAY,QAAQ,OAAO;AAC3B,cAAY,OAAO,OAAO,SAAS,OAAO,OAAO;GAE/C,IAAI;AAGJ,OAAI,SAAS,OAAO,UAAU;QACxB,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAK,IAAI,MAAM,KAAK,SAAS,EACjE,aAAY,MAAM,KAAK;aACd,MAAM,OAAO,OAAO,MAAM,QAAQ,SAC3C,aAAY,MAAM;aACT,MAAM,OAAO,MAAM,QAAQ,MAAM,IAAI,IAAI,MAAM,IAAI,SAAS,EACrE,aAAY,MAAM,IAAI;;AAI1B,OAAI,UACF,aAAY,QAAQ,IAAI,IAAI,UAAU;IAExC;;;;;;;;;;;;;;;;;;;;;;;;CAyBJ,WAAW,eAAoC;AAE7C,cAAY,eAAe;AAC3B,SAAO,YAAY;;;;;;;;;;;;;;;;;;;;;;;;CAyBrB,WAAW,SAA8B;AAEvC,cAAY,eAAe;AAC3B,SAAO,YAAY"}
1
+ {"version":3,"file":"Resource.js","names":[],"sources":["../src/Resource.ts"],"sourcesContent":["import { RpgClientEngine } from './RpgClientEngine';\n\n/**\n * RpgResource class\n * \n * Provides a unified API to access resource file links (images and sounds) in the game.\n * Resources are stored as Maps of resource IDs to file paths/URLs.\n * \n * ## Design\n * \n * RpgResource acts as a facade over the engine's resource storage, providing\n * easy access to resource file links. It maintains Maps that are synchronized\n * with the engine's internal storage, but only stores the file paths/URLs,\n * not the full resource objects.\n * \n * @example\n * ```ts\n * import { RpgResource } from '@rpgjs/client'\n * \n * // Get spritesheet image link\n * const imageLink = RpgResource.spritesheets.get('hero')\n * \n * // Get sound file link\n * const soundLink = RpgResource.sounds.get('town-music')\n * \n * // Set a new resource link\n * RpgResource.spritesheets.set('new-sprite', './assets/new-sprite.png')\n * ```\n */\nexport class RpgResource {\n private static engine: RpgClientEngine | null = null;\n private static _spritesheets: Map<string, string> = new Map();\n private static _sounds: Map<string, string> = new Map();\n\n /**\n * Initialize RpgResource with the engine instance\n * \n * This is called automatically by the engine during initialization.\n * It synchronizes the resource Maps with the engine's internal storage.\n * \n * @param engine - The RpgClientEngine instance\n */\n static init(engine: RpgClientEngine): void {\n RpgResource.engine = engine;\n RpgResource.syncResources();\n }\n\n /**\n * Synchronize resource Maps with the engine's internal storage\n * \n * Extracts file links from spritesheets and sounds stored in the engine\n * and updates the Maps accordingly.\n * \n * @private\n */\n private static syncResources(): void {\n if (!RpgResource.engine) {\n return;\n }\n\n // Sync spritesheets\n RpgResource._spritesheets.clear();\n RpgResource.engine.spritesheets.forEach((spritesheet, id) => {\n // Extract image path from spritesheet\n const imageLink = spritesheet?.image || spritesheet?.imageSource || undefined;\n if (imageLink) {\n RpgResource._spritesheets.set(id, imageLink);\n }\n });\n\n // Sync sounds\n RpgResource._sounds.clear();\n RpgResource.engine.sounds.forEach((sound, id) => {\n // Extract src path from sound\n let soundLink: string | undefined;\n \n // If it's a Howler instance, try to get src from _src or src property\n if (sound && typeof sound === 'object') {\n if (sound._src && Array.isArray(sound._src) && sound._src.length > 0) {\n soundLink = sound._src[0];\n } else if (sound.src && typeof sound.src === 'string') {\n soundLink = sound.src;\n } else if (sound.src && Array.isArray(sound.src) && sound.src.length > 0) {\n soundLink = sound.src[0];\n }\n }\n \n if (soundLink) {\n RpgResource._sounds.set(id, soundLink);\n }\n });\n }\n\n /**\n * Get/Set image links for spritesheets\n * \n * Map of spritesheet IDs to their image file paths/URLs.\n * This Map is synchronized with the engine's spritesheet storage.\n * \n * @type {Map<string, string>}\n * \n * @example\n * ```ts\n * // Get an image link\n * const imageLink = RpgResource.spritesheets.get('hero')\n * \n * // Set a new image link\n * RpgResource.spritesheets.set('new-sprite', './assets/new-sprite.png')\n * \n * // Check if a spritesheet exists\n * if (RpgResource.spritesheets.has('monster')) {\n * const link = RpgResource.spritesheets.get('monster')\n * }\n * ```\n */\n static get spritesheets(): Map<string, string> {\n // Sync before returning to ensure we have the latest data\n RpgResource.syncResources();\n return RpgResource._spritesheets;\n }\n\n /**\n * Get/Set sound file links\n * \n * Map of sound IDs to their audio file paths/URLs.\n * This Map is synchronized with the engine's sound storage.\n * \n * @type {Map<string, string>}\n * \n * @example\n * ```ts\n * // Get a sound link\n * const soundLink = RpgResource.sounds.get('town-music')\n * \n * // Set a new sound link\n * RpgResource.sounds.set('new-sound', './assets/new-sound.ogg')\n * \n * // Iterate over all sounds\n * RpgResource.sounds.forEach((link, id) => {\n * console.log(`Sound ${id}: ${link}`)\n * })\n * ```\n */\n static get sounds(): Map<string, string> {\n // Sync before returning to ensure we have the latest data\n RpgResource.syncResources();\n return RpgResource._sounds;\n }\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,IAAa,cAAb,MAAa,YAAY;;gBACyB;;;uCACI,IAAI,KAAK;;;iCACf,IAAI,KAAK;;;;;;;;;;CAUvD,OAAO,KAAK,QAA+B;EACzC,YAAY,SAAS;EACrB,YAAY,eAAe;;;;;;;;;;CAW7B,OAAe,gBAAsB;EACnC,IAAI,CAAC,YAAY,QACf;EAIF,YAAY,cAAc,OAAO;EACjC,YAAY,OAAO,aAAa,SAAS,aAAa,OAAO;GAE3D,MAAM,YAAY,aAAa,SAAS,aAAa,eAAe,KAAA;GACpE,IAAI,WACF,YAAY,cAAc,IAAI,IAAI,UAAU;IAE9C;EAGF,YAAY,QAAQ,OAAO;EAC3B,YAAY,OAAO,OAAO,SAAS,OAAO,OAAO;GAE/C,IAAI;GAGJ,IAAI,SAAS,OAAO,UAAU;QACxB,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAK,IAAI,MAAM,KAAK,SAAS,GACjE,YAAY,MAAM,KAAK;SAClB,IAAI,MAAM,OAAO,OAAO,MAAM,QAAQ,UAC3C,YAAY,MAAM;SACb,IAAI,MAAM,OAAO,MAAM,QAAQ,MAAM,IAAI,IAAI,MAAM,IAAI,SAAS,GACrE,YAAY,MAAM,IAAI;;GAI1B,IAAI,WACF,YAAY,QAAQ,IAAI,IAAI,UAAU;IAExC;;;;;;;;;;;;;;;;;;;;;;;;CAyBJ,WAAW,eAAoC;EAE7C,YAAY,eAAe;EAC3B,OAAO,YAAY;;;;;;;;;;;;;;;;;;;;;;;;CAyBrB,WAAW,SAA8B;EAEvC,YAAY,eAAe;EAC3B,OAAO,YAAY"}
@@ -5,6 +5,17 @@ import { RpgClientObject } from './Game/Object';
5
5
  import { MapPhysicsEntityContext, MapPhysicsInitContext } from '@rpgjs/common';
6
6
  type RpgComponent = RpgClientObject;
7
7
  type SceneMap = Container;
8
+ export interface RpgSpriteBeforeRemoveContext {
9
+ reason?: string;
10
+ data?: any;
11
+ transition?: {
12
+ animation?: string;
13
+ graphic?: string | string[];
14
+ duration?: number;
15
+ effect?: string;
16
+ };
17
+ timeoutMs?: number;
18
+ }
8
19
  export interface RpgClientEngineHooks {
9
20
  /**
10
21
  * When the engine is started. If you send false, you prevent the client from connecting to the server
@@ -103,6 +114,17 @@ export interface RpgSpriteHooks {
103
114
  * @memberof RpgSpriteHooks
104
115
  */
105
116
  onDestroy?: (sprite: RpgComponent) => any;
117
+ /**
118
+ * Called when a sprite removal is requested, before it disappears from the scene.
119
+ *
120
+ * Return a promise to keep the sprite visible while an animation, effect, or
121
+ * sound transition is running. The server still owns gameplay removal and
122
+ * uses the timeout carried by the remove request as a safety limit.
123
+ *
124
+ * @prop { (sprite: RpgSprite, context: RpgSpriteBeforeRemoveContext) => any } [onBeforeRemove]
125
+ * @memberof RpgSpriteHooks
126
+ */
127
+ onBeforeRemove?: (sprite: RpgComponent, context: RpgSpriteBeforeRemoveContext) => any;
106
128
  /**
107
129
  * As soon as a data is changed on the server side (the name for example), you are able to know the new data but also the old data.
108
130
  *
@@ -15,8 +15,8 @@ export declare class RpgClientEngine<T = any> {
15
15
  globalConfig: T;
16
16
  sceneComponent: any;
17
17
  stopProcessingInput: boolean;
18
- width: import('canvasengine').WritableSignal<string>;
19
- height: import('canvasengine').WritableSignal<string>;
18
+ width: any;
19
+ height: any;
20
20
  spritesheets: Map<string, any>;
21
21
  sounds: Map<string, any>;
22
22
  componentAnimations: any[];
@@ -29,15 +29,15 @@ export declare class RpgClientEngine<T = any> {
29
29
  tick: Observable<number>;
30
30
  private canvasApp?;
31
31
  private canvasElement?;
32
- playerIdSignal: import('canvasengine').WritableSignal<string | null>;
33
- spriteComponentsBehind: import('canvasengine').WritableArraySignal<any[]>;
34
- spriteComponentsInFront: import('canvasengine').WritableArraySignal<any[]>;
32
+ playerIdSignal: any;
33
+ spriteComponentsBehind: any;
34
+ spriteComponentsInFront: any;
35
35
  /** ID of the sprite that the camera should follow. null means follow the current player */
36
- cameraFollowTargetId: import('canvasengine').WritableSignal<string | null>;
36
+ cameraFollowTargetId: any;
37
37
  /** Trigger for map shake animation */
38
- mapShakeTrigger: import('canvasengine').Trigger<any>;
39
- controlsReady: import('canvasengine').WritableSignal<undefined>;
40
- gamePause: import('canvasengine').WritableSignal<boolean>;
38
+ mapShakeTrigger: any;
39
+ controlsReady: any;
40
+ gamePause: any;
41
41
  private predictionEnabled;
42
42
  private prediction?;
43
43
  private readonly SERVER_CORRECTION_THRESHOLD;
@@ -520,9 +520,12 @@ export declare class RpgClientEngine<T = any> {
520
520
  * duration: 1000,
521
521
  * onFinish: () => console.log('Fade complete')
522
522
  * });
523
+ *
524
+ * // Wait until the transition component calls onFinish
525
+ * await engine.startTransition('fade', { duration: 1000 });
523
526
  * ```
524
527
  */
525
- startTransition(id: string, props?: any): void;
528
+ startTransition(id: string, props?: any): Promise<void>;
526
529
  processInput({ input }: {
527
530
  input: Direction;
528
531
  }): Promise<void>;
@@ -531,7 +534,7 @@ export declare class RpgClientEngine<T = any> {
531
534
  }): void;
532
535
  get PIXI(): typeof PIXI;
533
536
  get socket(): AbstractWebsocket;
534
- get playerId(): string | null;
537
+ get playerId(): any;
535
538
  get scene(): RpgClientMap;
536
539
  private getPhysicsTick;
537
540
  private ensureCurrentPlayerBody;
@@ -543,7 +546,7 @@ export declare class RpgClientEngine<T = any> {
543
546
  private getLocalPlayerState;
544
547
  private applyAuthoritativeState;
545
548
  private initializePredictionController;
546
- getCurrentPlayer(): import('.').RpgClientPlayer;
549
+ getCurrentPlayer(): any;
547
550
  emitSceneMapHook(hookName: string, ...args: any[]): void;
548
551
  /**
549
552
  * Setup RxJS observer to wait for all conditions before calling onAfterLoading hook
@@ -2,11 +2,11 @@ import { inject } from "./core/inject.js";
2
2
  import { WebSocketToken } from "./services/AbstractSocket.js";
3
3
  import { SaveClientService } from "./services/save.js";
4
4
  import { RpgGui } from "./Gui/Gui.js";
5
- import component from "./components/scenes/canvas.ce.js";
5
+ import __ce_component from "./components/scenes/canvas.ce.js";
6
6
  import { LoadMapToken } from "./services/loadMap.js";
7
7
  import { RpgSound } from "./Sound.js";
8
8
  import { RpgResource } from "./Resource.js";
9
- import { load } from "./node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js";
9
+ import { load } from "./node_modules/.pnpm/@signe_sync@2.10.0/node_modules/@signe/sync/dist/index.js";
10
10
  import { RpgClientMap } from "./Game/Map.js";
11
11
  import { AnimationManager } from "./Game/AnimationManager.js";
12
12
  import { GlobalConfigToken } from "./module.js";
@@ -122,7 +122,7 @@ var RpgClientEngine = class {
122
122
  this.sceneMap.loadPhysic();
123
123
  this.selector = document.body.querySelector("#rpg");
124
124
  const bootstrapOptions = this.globalConfig?.bootstrapCanvasOptions;
125
- const { app, canvasElement } = await bootstrapCanvas(this.selector, component, bootstrapOptions);
125
+ const { app, canvasElement } = await bootstrapCanvas(this.selector, __ce_component, bootstrapOptions);
126
126
  this.canvasApp = app;
127
127
  this.canvasElement = canvasElement;
128
128
  this.renderer = app.renderer;
@@ -888,11 +888,26 @@ var RpgClientEngine = class {
888
888
  * duration: 1000,
889
889
  * onFinish: () => console.log('Fade complete')
890
890
  * });
891
+ *
892
+ * // Wait until the transition component calls onFinish
893
+ * await engine.startTransition('fade', { duration: 1000 });
891
894
  * ```
892
895
  */
893
896
  startTransition(id, props = {}) {
894
897
  if (!this.guiService.exists(id)) throw new Error(`Transition with id ${id} not found. Make sure to add it using engine.addTransition() or in your module's transitions property.`);
895
- this.guiService.display(id, props);
898
+ return new Promise((resolve) => {
899
+ let finished = false;
900
+ const finish = (data) => {
901
+ if (finished) return;
902
+ finished = true;
903
+ props?.onFinish?.(data);
904
+ resolve();
905
+ };
906
+ this.guiService.display(id, {
907
+ ...props,
908
+ onFinish: finish
909
+ });
910
+ });
896
911
  }
897
912
  async processInput({ input }) {
898
913
  if (this.stopProcessingInput) return;