@rpgjs/client 5.0.0-alpha.14 → 5.0.0-alpha.15

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 (44) hide show
  1. package/dist/Game/Map.d.ts +2 -1
  2. package/dist/RpgClient.d.ts +39 -0
  3. package/dist/RpgClientEngine.d.ts +138 -2
  4. package/dist/index10.js +1 -2
  5. package/dist/index10.js.map +1 -1
  6. package/dist/index15.js +58 -16
  7. package/dist/index15.js.map +1 -1
  8. package/dist/index2.js +303 -3
  9. package/dist/index2.js.map +1 -1
  10. package/dist/index20.js +3 -0
  11. package/dist/index20.js.map +1 -1
  12. package/dist/index22.js +3 -3
  13. package/dist/index23.js +2 -2
  14. package/dist/index25.js +1 -2
  15. package/dist/index25.js.map +1 -1
  16. package/dist/index33.js +1 -1
  17. package/dist/index34.js +1 -1
  18. package/dist/index35.js +9 -184
  19. package/dist/index35.js.map +1 -1
  20. package/dist/index36.js +6 -503
  21. package/dist/index36.js.map +1 -1
  22. package/dist/index37.js +3687 -9
  23. package/dist/index37.js.map +1 -1
  24. package/dist/index38.js +186 -6
  25. package/dist/index38.js.map +1 -1
  26. package/dist/index39.js +499 -3685
  27. package/dist/index39.js.map +1 -1
  28. package/dist/index40.js +1 -1
  29. package/dist/index41.js +1 -1
  30. package/dist/index42.js +119 -16
  31. package/dist/index42.js.map +1 -1
  32. package/dist/index43.js +16 -92
  33. package/dist/index43.js.map +1 -1
  34. package/dist/index8.js +8 -0
  35. package/dist/index8.js.map +1 -1
  36. package/package.json +4 -4
  37. package/src/Game/Map.ts +5 -1
  38. package/src/Game/Object.ts +37 -4
  39. package/src/RpgClient.ts +40 -0
  40. package/src/RpgClientEngine.ts +374 -11
  41. package/src/components/animations/animation.ce +1 -2
  42. package/src/components/character.ce +80 -20
  43. package/src/components/gui/dialogbox/index.ce +1 -2
  44. package/src/module.ts +8 -0
package/dist/index40.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { useProps, useDefineProps, mount, signal, h, Container, loop, Howl, computed } from 'canvasengine';
2
- import component$1 from './index42.js';
2
+ import component$1 from './index43.js';
3
3
  import { RpgClientEngine } from './index2.js';
4
4
  import { inject } from './index6.js';
5
5
 
package/dist/index41.js CHANGED
@@ -1,4 +1,4 @@
1
- import * as external from './index38.js';
1
+ import * as external from './index36.js';
2
2
 
3
3
 
4
4
 
package/dist/index42.js CHANGED
@@ -1,20 +1,123 @@
1
- import { useProps, useDefineProps, animatedSignal, h, Container, Rect, Text } from 'canvasengine';
1
+ import { RpgCommonPlayer, ModulesToken } from '@rpgjs/common';
2
+ import { trigger, signal } from 'canvasengine';
3
+ import { inject } from './index6.js';
4
+ import { RpgClientEngine } from './index2.js';
2
5
 
3
- function component($$props) {
4
- useProps($$props);
5
- const defineProps = useDefineProps($$props);
6
- var _a = defineProps(), text = _a.text, isSelected = _a.isSelected;
7
- var alpha = animatedSignal(1, {
8
- repeatType: "reverse",
9
- duration: 500,
10
- repeat: Infinity,
11
- });
12
- alpha.set(0.5);
13
- var height = 40;
14
- var width = 256;
15
- let $this = h(Container, null, [h(Rect, { width, height, color: '#595971', alpha, visible: isSelected }), h(Container, { flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }, h(Text, { text, color: '#fff', fontSize: 18, margin: 10 }))]);
16
- return $this
6
+ class RpgClientObject extends RpgCommonPlayer {
7
+ constructor() {
8
+ super();
9
+ this.emitParticleTrigger = trigger();
10
+ this.particleName = signal("");
11
+ this.animationCurrentIndex = signal(0);
12
+ this.animationIsPlaying = signal(false);
13
+ this._param = signal({});
14
+ this.frames = [];
15
+ this.hooks.callHooks("client-sprite-onInit", this).subscribe();
16
+ this._frames.observable.subscribe(({ items }) => {
17
+ if (!this.id) return;
18
+ this.frames = [...this.frames, ...items];
19
+ });
20
+ this.engine.tick.pipe(
21
+ //throttleTime(10)
22
+ ).subscribe(() => {
23
+ const frame = this.frames.shift();
24
+ if (frame) {
25
+ const entity = this.engine.scene.getBody(this.id);
26
+ const isLocalPlayer = this.id === this.engine.playerIdSignal();
27
+ if (entity && !isLocalPlayer) {
28
+ const { x: oldX, y: oldY } = entity.position;
29
+ const dt = 1 / 60;
30
+ const velocity = {
31
+ x: (frame.x - oldX) / dt,
32
+ y: (frame.y - oldY) / dt
33
+ };
34
+ entity.setVelocity(velocity);
35
+ }
36
+ this.engine.scene.setBodyPosition(this.id, frame.x, frame.y);
17
37
  }
38
+ });
39
+ }
40
+ get hooks() {
41
+ return inject(ModulesToken);
42
+ }
43
+ get engine() {
44
+ return inject(RpgClientEngine);
45
+ }
46
+ flash(color, duration = 100) {
47
+ return new Promise((resolve) => {
48
+ const lastTint = this.tint();
49
+ this.tint.set(color);
50
+ setTimeout(() => {
51
+ this.tint.set(lastTint);
52
+ resolve(true);
53
+ }, duration);
54
+ });
55
+ }
56
+ /**
57
+ * Reset animation state when animation changes externally
58
+ *
59
+ * This method should be called when the animation changes due to movement
60
+ * or other external factors to ensure the animation system doesn't get stuck
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * // Reset when player starts moving
65
+ * player.resetAnimationState();
66
+ * ```
67
+ */
68
+ resetAnimationState() {
69
+ this.animationIsPlaying.set(false);
70
+ this.animationCurrentIndex.set(0);
71
+ if (this.animationSubscription) {
72
+ this.animationSubscription.unsubscribe();
73
+ this.animationSubscription = void 0;
74
+ }
75
+ }
76
+ /**
77
+ * Set a custom animation for a specific number of times
78
+ *
79
+ * Plays a custom animation for the specified number of repetitions.
80
+ * The animation system prevents overlapping animations and automatically
81
+ * returns to the previous animation when complete.
82
+ *
83
+ * @param animationName - Name of the animation to play
84
+ * @param nbTimes - Number of times to repeat the animation (default: Infinity for continuous)
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * // Play attack animation 3 times
89
+ * player.setAnimation('attack', 3);
90
+ *
91
+ * // Play continuous spell animation
92
+ * player.setAnimation('spell');
93
+ * ```
94
+ */
95
+ setAnimation(animationName, nbTimes = Infinity) {
96
+ if (this.animationIsPlaying()) return;
97
+ this.animationIsPlaying.set(true);
98
+ const previousAnimationName = this.animationName();
99
+ this.animationCurrentIndex.set(0);
100
+ if (this.animationSubscription) {
101
+ this.animationSubscription.unsubscribe();
102
+ }
103
+ this.animationSubscription = this.animationCurrentIndex.observable.subscribe((index) => {
104
+ if (index >= nbTimes) {
105
+ this.animationCurrentIndex.set(0);
106
+ this.animationName.set(previousAnimationName);
107
+ this.animationIsPlaying.set(false);
108
+ if (this.animationSubscription) {
109
+ this.animationSubscription.unsubscribe();
110
+ this.animationSubscription = void 0;
111
+ }
112
+ }
113
+ });
114
+ this.animationName.set(animationName);
115
+ }
116
+ showComponentAnimation(id, params) {
117
+ const engine = inject(RpgClientEngine);
118
+ engine.getComponentAnimation(id).displayEffect(params, this);
119
+ }
120
+ }
18
121
 
19
- export { component as default };
122
+ export { RpgClientObject };
20
123
  //# sourceMappingURL=index42.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index42.js","sources":["../src/components/gui/dialogbox/itemMenu.ce"],"sourcesContent":["<Container>\n <Rect width height color=\"#595971\" alpha visible={isSelected} />\n <Container flexDirection=\"row\" alignItems=\"center\" justifyContent=\"center\">\n <Text text color=\"#fff\" fontSize={18} margin={10} />\n </Container>\n</Container>\n\n<script>\nimport { animatedSignal } from \"canvasengine\";\n\nconst { text, isSelected } = defineProps();\n\nconst alpha = animatedSignal(1, {\n repeatType: \"reverse\",\n duration: 500,\n repeat: Infinity,\n});\n\nalpha.set(0.5);\n\nconst height = 40;\nconst width = 256;\n</script>"],"names":[],"mappings":";;AAQqB,SAAS,SAAS,CAAC,OAAO,EAAE;AACjD,QAAuB,QAAQ,CAAC,OAAO;AACvC,QAAQ,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO;AAClD,QAAQ,IAAI,EAAE,GAAG,WAAW,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,EAAE,CAAC,UAAU;AAC1E,IAAI,KAAK,GAAG,cAAc,CAAC,CAAC,EAAE;AAC9B,IAAI,UAAU,EAAE,SAAS;AACzB,IAAI,QAAQ,EAAE,GAAG;AACjB,IAAI,MAAM,EAAE,QAAQ;AACpB,CAAC,CAAC;AACF,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;AACd,IAAI,MAAM,GAAG,EAAE;AACf,IAAI,KAAK,GAAG,GAAG;AACf,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACrQ,QAAQ,OAAO;AACf,MAAM;;;;"}
1
+ {"version":3,"file":"index42.js","sources":["../src/Game/Object.ts"],"sourcesContent":["import { Hooks, ModulesToken, RpgCommonPlayer } from \"@rpgjs/common\";\nimport { sync } from \"@signe/sync\";\nimport { trigger, signal } from \"canvasengine\";\nimport { debounceTime, Subscription, throttleTime } from \"rxjs\";\nimport { inject } from \"../core/inject\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\n\nexport abstract class RpgClientObject extends RpgCommonPlayer {\n abstract type: string;\n emitParticleTrigger = trigger()\n particleName = signal('')\n animationCurrentIndex = signal(0)\n animationIsPlaying = signal(false)\n _param = signal({})\n frames: { x: number; y: number; ts: number }[] = []\n\n constructor() {\n super()\n this.hooks.callHooks(\"client-sprite-onInit\", this).subscribe();\n\n this._frames.observable.subscribe(({ items }) => {\n if (!this.id) return;\n //if (this.id == this.engine.playerIdSignal()!) return;\n this.frames = [...this.frames, ...items]\n })\n\n this.engine.tick\n .pipe(\n //throttleTime(10)\n )\n .subscribe(() => {\n const frame = this.frames.shift()\n if (frame) {\n const entity = this.engine.scene.getBody(this.id)\n const isLocalPlayer = this.id === this.engine.playerIdSignal()\n if (entity && !isLocalPlayer) {\n const { x: oldX, y: oldY } = entity.position\n const dt = 1 / 60 // Assume 60 FPS for now\n const velocity = {\n x: (frame.x - oldX) / dt,\n y: (frame.y - oldY) / dt\n }\n entity.setVelocity(velocity)\n }\n this.engine.scene.setBodyPosition(this.id, frame.x, frame.y)\n }\n })\n }\n\n get hooks() {\n return inject<Hooks>(ModulesToken);\n }\n\n get engine() {\n return inject(RpgClientEngine)\n }\n\n private animationSubscription?: Subscription\n\n flash(color: string, duration: number = 100) {\n return new Promise((resolve) => {\n const lastTint = this.tint()\n this.tint.set(color);\n setTimeout(() => {\n this.tint.set(lastTint)\n resolve(true)\n }, duration)\n })\n }\n\n /**\n * Reset animation state when animation changes externally\n * \n * This method should be called when the animation changes due to movement\n * or other external factors to ensure the animation system doesn't get stuck\n * \n * @example\n * ```ts\n * // Reset when player starts moving\n * player.resetAnimationState();\n * ```\n */\n resetAnimationState() {\n this.animationIsPlaying.set(false);\n this.animationCurrentIndex.set(0);\n if (this.animationSubscription) {\n this.animationSubscription.unsubscribe();\n this.animationSubscription = undefined;\n }\n }\n\n /**\n * Set a custom animation for a specific number of times\n * \n * Plays a custom animation for the specified number of repetitions.\n * The animation system prevents overlapping animations and automatically\n * returns to the previous animation when complete.\n * \n * @param animationName - Name of the animation to play\n * @param nbTimes - Number of times to repeat the animation (default: Infinity for continuous)\n * \n * @example\n * ```ts\n * // Play attack animation 3 times\n * player.setAnimation('attack', 3);\n * \n * // Play continuous spell animation\n * player.setAnimation('spell');\n * ```\n */\n setAnimation(animationName: string, nbTimes: number = Infinity) {\n if (this.animationIsPlaying()) return;\n this.animationIsPlaying.set(true);\n const previousAnimationName = this.animationName();\n this.animationCurrentIndex.set(0);\n\n // Clean up any existing subscription\n if (this.animationSubscription) {\n this.animationSubscription.unsubscribe();\n }\n\n this.animationSubscription = this.animationCurrentIndex.observable.subscribe(index => {\n if (index >= nbTimes) {\n this.animationCurrentIndex.set(0);\n this.animationName.set(previousAnimationName);\n this.animationIsPlaying.set(false);\n if (this.animationSubscription) {\n this.animationSubscription.unsubscribe();\n this.animationSubscription = undefined;\n }\n }\n })\n this.animationName.set(animationName);\n }\n\n showComponentAnimation(id: string, params: any) {\n const engine = inject(RpgClientEngine)\n engine.getComponentAnimation(id).displayEffect(params, this)\n }\n} "],"names":[],"mappings":"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"}
package/dist/index43.js CHANGED
@@ -1,96 +1,20 @@
1
- import { RpgCommonPlayer, ModulesToken } from '@rpgjs/common';
2
- import { trigger, signal } from 'canvasengine';
3
- import { inject } from './index6.js';
4
- import { RpgClientEngine } from './index2.js';
1
+ import { useProps, useDefineProps, animatedSignal, h, Container, Rect, Text } from 'canvasengine';
5
2
 
6
- class RpgClientObject extends RpgCommonPlayer {
7
- constructor() {
8
- super();
9
- this.emitParticleTrigger = trigger();
10
- this.particleName = signal("");
11
- this.animationCurrentIndex = signal(0);
12
- this.animationIsPlaying = signal(false);
13
- this._param = signal({});
14
- this.hooks.callHooks("client-sprite-onInit", this).subscribe();
15
- }
16
- get hooks() {
17
- return inject(ModulesToken);
18
- }
19
- flash(color, duration = 100) {
20
- return new Promise((resolve) => {
21
- const lastTint = this.tint();
22
- this.tint.set(color);
23
- setTimeout(() => {
24
- this.tint.set(lastTint);
25
- resolve(true);
26
- }, duration);
27
- });
28
- }
29
- /**
30
- * Reset animation state when animation changes externally
31
- *
32
- * This method should be called when the animation changes due to movement
33
- * or other external factors to ensure the animation system doesn't get stuck
34
- *
35
- * @example
36
- * ```ts
37
- * // Reset when player starts moving
38
- * player.resetAnimationState();
39
- * ```
40
- */
41
- resetAnimationState() {
42
- this.animationIsPlaying.set(false);
43
- this.animationCurrentIndex.set(0);
44
- if (this.animationSubscription) {
45
- this.animationSubscription.unsubscribe();
46
- this.animationSubscription = void 0;
47
- }
48
- }
49
- /**
50
- * Set a custom animation for a specific number of times
51
- *
52
- * Plays a custom animation for the specified number of repetitions.
53
- * The animation system prevents overlapping animations and automatically
54
- * returns to the previous animation when complete.
55
- *
56
- * @param animationName - Name of the animation to play
57
- * @param nbTimes - Number of times to repeat the animation (default: Infinity for continuous)
58
- *
59
- * @example
60
- * ```ts
61
- * // Play attack animation 3 times
62
- * player.setAnimation('attack', 3);
63
- *
64
- * // Play continuous spell animation
65
- * player.setAnimation('spell');
66
- * ```
67
- */
68
- setAnimation(animationName, nbTimes = Infinity) {
69
- if (this.animationIsPlaying()) return;
70
- this.animationIsPlaying.set(true);
71
- const previousAnimationName = this.animationName();
72
- this.animationCurrentIndex.set(0);
73
- if (this.animationSubscription) {
74
- this.animationSubscription.unsubscribe();
75
- }
76
- this.animationSubscription = this.animationCurrentIndex.observable.subscribe((index) => {
77
- if (index >= nbTimes) {
78
- this.animationCurrentIndex.set(0);
79
- this.animationName.set(previousAnimationName);
80
- this.animationIsPlaying.set(false);
81
- if (this.animationSubscription) {
82
- this.animationSubscription.unsubscribe();
83
- this.animationSubscription = void 0;
84
- }
3
+ function component($$props) {
4
+ useProps($$props);
5
+ const defineProps = useDefineProps($$props);
6
+ var _a = defineProps(), text = _a.text, isSelected = _a.isSelected;
7
+ var alpha = animatedSignal(1, {
8
+ repeatType: "reverse",
9
+ duration: 500,
10
+ repeat: Infinity,
11
+ });
12
+ alpha.set(0.5);
13
+ var height = 40;
14
+ var width = 256;
15
+ let $this = h(Container, null, [h(Rect, { width, height, color: '#595971', alpha, visible: isSelected }), h(Container, { flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }, h(Text, { text, color: '#fff', fontSize: 18, margin: 10 }))]);
16
+ return $this
85
17
  }
86
- });
87
- this.animationName.set(animationName);
88
- }
89
- showComponentAnimation(id, params) {
90
- const engine = inject(RpgClientEngine);
91
- engine.getComponentAnimation(id).displayEffect(params, this);
92
- }
93
- }
94
18
 
95
- export { RpgClientObject };
19
+ export { component as default };
96
20
  //# sourceMappingURL=index43.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index43.js","sources":["../src/Game/Object.ts"],"sourcesContent":["import { Hooks, ModulesToken, RpgCommonPlayer } from \"@rpgjs/common\";\nimport { sync } from \"@signe/sync\";\nimport { trigger, signal } from \"canvasengine\";\nimport { Subscription } from \"rxjs\";\nimport { inject } from \"../core/inject\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\n\nexport abstract class RpgClientObject extends RpgCommonPlayer {\n abstract type: string;\n emitParticleTrigger = trigger()\n particleName = signal('')\n animationCurrentIndex = signal(0)\n animationIsPlaying = signal(false)\n _param = signal({})\n\n constructor() {\n super()\n this.hooks.callHooks(\"client-sprite-onInit\", this).subscribe();\n }\n\n get hooks() {\n return inject<Hooks>(ModulesToken);\n }\n \n private animationSubscription?: Subscription\n\n flash(color: string, duration: number = 100) {\n return new Promise((resolve) => {\n const lastTint = this.tint()\n this.tint.set(color);\n setTimeout(() => {\n this.tint.set(lastTint)\n resolve(true)\n }, duration)\n })\n }\n\n /**\n * Reset animation state when animation changes externally\n * \n * This method should be called when the animation changes due to movement\n * or other external factors to ensure the animation system doesn't get stuck\n * \n * @example\n * ```ts\n * // Reset when player starts moving\n * player.resetAnimationState();\n * ```\n */\n resetAnimationState() {\n this.animationIsPlaying.set(false);\n this.animationCurrentIndex.set(0);\n if (this.animationSubscription) {\n this.animationSubscription.unsubscribe();\n this.animationSubscription = undefined;\n }\n }\n\n /**\n * Set a custom animation for a specific number of times\n * \n * Plays a custom animation for the specified number of repetitions.\n * The animation system prevents overlapping animations and automatically\n * returns to the previous animation when complete.\n * \n * @param animationName - Name of the animation to play\n * @param nbTimes - Number of times to repeat the animation (default: Infinity for continuous)\n * \n * @example\n * ```ts\n * // Play attack animation 3 times\n * player.setAnimation('attack', 3);\n * \n * // Play continuous spell animation\n * player.setAnimation('spell');\n * ```\n */\n setAnimation(animationName: string, nbTimes: number = Infinity) {\n if (this.animationIsPlaying()) return;\n this.animationIsPlaying.set(true);\n const previousAnimationName = this.animationName();\n this.animationCurrentIndex.set(0);\n \n // Clean up any existing subscription\n if (this.animationSubscription) {\n this.animationSubscription.unsubscribe();\n }\n \n this.animationSubscription = this.animationCurrentIndex.observable.subscribe(index => {\n if (index >= nbTimes) {\n this.animationCurrentIndex.set(0);\n this.animationName.set(previousAnimationName);\n this.animationIsPlaying.set(false);\n if (this.animationSubscription) {\n this.animationSubscription.unsubscribe();\n this.animationSubscription = undefined;\n }\n }\n })\n this.animationName.set(animationName);\n }\n\n showComponentAnimation(id: string, params: any) {\n const engine = inject(RpgClientEngine)\n engine.getComponentAnimation(id).displayEffect(params, this)\n }\n} "],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index43.js","sources":["../src/components/gui/dialogbox/itemMenu.ce"],"sourcesContent":["<Container>\n <Rect width height color=\"#595971\" alpha visible={isSelected} />\n <Container flexDirection=\"row\" alignItems=\"center\" justifyContent=\"center\">\n <Text text color=\"#fff\" fontSize={18} margin={10} />\n </Container>\n</Container>\n\n<script>\nimport { animatedSignal } from \"canvasengine\";\n\nconst { text, isSelected } = defineProps();\n\nconst alpha = animatedSignal(1, {\n repeatType: \"reverse\",\n duration: 500,\n repeat: Infinity,\n});\n\nalpha.set(0.5);\n\nconst height = 40;\nconst width = 256;\n</script>"],"names":[],"mappings":";;AAQqB,SAAS,SAAS,CAAC,OAAO,EAAE;AACjD,QAAuB,QAAQ,CAAC,OAAO;AACvC,QAAQ,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO;AAClD,QAAQ,IAAI,EAAE,GAAG,WAAW,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,EAAE,CAAC,UAAU;AAC1E,IAAI,KAAK,GAAG,cAAc,CAAC,CAAC,EAAE;AAC9B,IAAI,UAAU,EAAE,SAAS;AACzB,IAAI,QAAQ,EAAE,GAAG;AACjB,IAAI,MAAM,EAAE,QAAQ;AACpB,CAAC,CAAC;AACF,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;AACd,IAAI,MAAM,GAAG,EAAE;AACf,IAAI,KAAK,GAAG,GAAG;AACf,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACrQ,QAAQ,OAAO;AACf,MAAM;;;;"}
package/dist/index8.js CHANGED
@@ -20,6 +20,14 @@ function provideClientModules(modules) {
20
20
  }
21
21
  };
22
22
  }
23
+ if (module.spritesheetResolver) {
24
+ const resolver = module.spritesheetResolver;
25
+ module.spritesheetResolver = {
26
+ load: (engine) => {
27
+ engine.setSpritesheetResolver(resolver);
28
+ }
29
+ };
30
+ }
23
31
  if (module.sounds) {
24
32
  const sounds = [...module.sounds];
25
33
  module.sounds = {
@@ -1 +1 @@
1
- {"version":3,"file":"index8.js","sources":["../src/module.ts"],"sourcesContent":["import { findModules, provideModules } from \"@rpgjs/common\";\nimport { RpgClientEngine } from \"./RpgClientEngine\";\nimport { RpgClient } from \"./RpgClient\";\nimport { inject } from \"@signe/di\";\nimport { RpgGui } from \"./Gui/Gui\";\n\nexport function provideClientModules(modules: RpgClient[]) {\n return provideModules(modules, \"client\", (modules, context) => {\n const mainModuleClient = findModules(context, 'Client')\n modules = [...mainModuleClient, ...modules]\n modules = modules.map((module) => {\n if ('client' in module) {\n module = module.client as any;\n }\n if (module.spritesheets) {\n const spritesheets = [...module.spritesheets];\n module.spritesheets = {\n load: (engine: RpgClientEngine) => {\n spritesheets.forEach((spritesheet) => {\n engine.addSpriteSheet(spritesheet);\n });\n },\n };\n }\n if (module.sounds) {\n const sounds = [...module.sounds];\n module.sounds = {\n load: (engine: RpgClientEngine) => {\n sounds.forEach((sound) => {\n engine.addSound(sound);\n });\n },\n };\n }\n if (module.gui) {\n const gui = [...module.gui];\n module.gui = {\n load: (engine: RpgClientEngine) => {\n const guiService = inject(engine.context, RpgGui);\n gui.forEach((gui) => {\n guiService.add(gui);\n });\n },\n };\n }\n if (module.componentAnimations) {\n const componentAnimations = [...module.componentAnimations];\n module.componentAnimations = {\n load: (engine: RpgClientEngine) => {\n componentAnimations.forEach((componentAnimation) => {\n engine.addComponentAnimation(componentAnimation);\n });\n },\n };\n }\n if (module.particles) {\n const particles = [...module.particles];\n module.particles = {\n load: (engine: RpgClientEngine) => {\n particles.forEach((particle) => {\n engine.addParticle(particle);\n });\n },\n };\n }\n if (module.sprite) {\n const sprite = {...module.sprite};\n module.sprite = {\n ...sprite,\n load: (engine: RpgClientEngine) => {\n if (sprite.componentsBehind) {\n sprite.componentsBehind.forEach((component) => {\n engine.addSpriteComponentBehind(component);\n });\n }\n if (sprite.componentsInFront) {\n sprite.componentsInFront.forEach((component) => {\n engine.addSpriteComponentInFront(component);\n });\n }\n },\n };\n }\n return module;\n });\n return modules\n });\n}\n\nexport const GlobalConfigToken = \"GlobalConfigToken\";\n\nexport function provideGlobalConfig(config: any) {\n return {\n provide: GlobalConfigToken,\n useValue: config ?? {},\n };\n}\n\nexport function provideClientGlobalConfig(config: any = {}) {\n if (!config.keyboardControls) {\n config.keyboardControls = {\n up: 'up',\n down: 'down',\n left: 'left',\n right: 'right',\n action: 'space'\n }\n }\n return provideGlobalConfig(config)\n}\n\n"],"names":["modules","gui"],"mappings":"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"}
1
+ {"version":3,"file":"index8.js","sources":["../src/module.ts"],"sourcesContent":["import { findModules, provideModules } from \"@rpgjs/common\";\nimport { RpgClientEngine } from \"./RpgClientEngine\";\nimport { RpgClient } from \"./RpgClient\";\nimport { inject } from \"@signe/di\";\nimport { RpgGui } from \"./Gui/Gui\";\n\nexport function provideClientModules(modules: RpgClient[]) {\n return provideModules(modules, \"client\", (modules, context) => {\n const mainModuleClient = findModules(context, 'Client')\n modules = [...mainModuleClient, ...modules]\n modules = modules.map((module) => {\n if ('client' in module) {\n module = module.client as any;\n }\n if (module.spritesheets) {\n const spritesheets = [...module.spritesheets];\n module.spritesheets = {\n load: (engine: RpgClientEngine) => {\n spritesheets.forEach((spritesheet) => {\n engine.addSpriteSheet(spritesheet);\n });\n },\n };\n }\n if (module.spritesheetResolver) {\n const resolver = module.spritesheetResolver;\n module.spritesheetResolver = {\n load: (engine: RpgClientEngine) => {\n engine.setSpritesheetResolver(resolver);\n },\n };\n }\n if (module.sounds) {\n const sounds = [...module.sounds];\n module.sounds = {\n load: (engine: RpgClientEngine) => {\n sounds.forEach((sound) => {\n engine.addSound(sound);\n });\n },\n };\n }\n if (module.gui) {\n const gui = [...module.gui];\n module.gui = {\n load: (engine: RpgClientEngine) => {\n const guiService = inject(engine.context, RpgGui);\n gui.forEach((gui) => {\n guiService.add(gui);\n });\n },\n };\n }\n if (module.componentAnimations) {\n const componentAnimations = [...module.componentAnimations];\n module.componentAnimations = {\n load: (engine: RpgClientEngine) => {\n componentAnimations.forEach((componentAnimation) => {\n engine.addComponentAnimation(componentAnimation);\n });\n },\n };\n }\n if (module.particles) {\n const particles = [...module.particles];\n module.particles = {\n load: (engine: RpgClientEngine) => {\n particles.forEach((particle) => {\n engine.addParticle(particle);\n });\n },\n };\n }\n if (module.sprite) {\n const sprite = {...module.sprite};\n module.sprite = {\n ...sprite,\n load: (engine: RpgClientEngine) => {\n if (sprite.componentsBehind) {\n sprite.componentsBehind.forEach((component) => {\n engine.addSpriteComponentBehind(component);\n });\n }\n if (sprite.componentsInFront) {\n sprite.componentsInFront.forEach((component) => {\n engine.addSpriteComponentInFront(component);\n });\n }\n },\n };\n }\n return module;\n });\n return modules\n });\n}\n\nexport const GlobalConfigToken = \"GlobalConfigToken\";\n\nexport function provideGlobalConfig(config: any) {\n return {\n provide: GlobalConfigToken,\n useValue: config ?? {},\n };\n}\n\nexport function provideClientGlobalConfig(config: any = {}) {\n if (!config.keyboardControls) {\n config.keyboardControls = {\n up: 'up',\n down: 'down',\n left: 'left',\n right: 'right',\n action: 'space'\n }\n }\n return provideGlobalConfig(config)\n}\n\n"],"names":["modules","gui"],"mappings":";;;;AAMO,SAAS,qBAAqB,OAAA,EAAsB;AACzD,EAAA,OAAO,cAAA,CAAe,OAAA,EAAS,QAAA,EAAU,CAACA,UAAS,OAAA,KAAY;AAC7D,IAAA,MAAM,gBAAA,GAAmB,WAAA,CAAY,OAAA,EAAS,QAAQ,CAAA;AACtD,IAAAA,QAAAA,GAAU,CAAC,GAAG,gBAAA,EAAkB,GAAGA,QAAO,CAAA;AAC1C,IAAAA,QAAAA,GAAUA,QAAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AAChC,MAAA,IAAI,YAAY,MAAA,EAAQ;AACtB,QAAA,MAAA,GAAS,MAAA,CAAO,MAAA;AAAA,MAClB;AACA,MAAA,IAAI,OAAO,YAAA,EAAc;AACvB,QAAA,MAAM,YAAA,GAAe,CAAC,GAAG,MAAA,CAAO,YAAY,CAAA;AAC5C,QAAA,MAAA,CAAO,YAAA,GAAe;AAAA,UACpB,IAAA,EAAM,CAAC,MAAA,KAA4B;AACjC,YAAA,YAAA,CAAa,OAAA,CAAQ,CAAC,WAAA,KAAgB;AACpC,cAAA,MAAA,CAAO,eAAe,WAAW,CAAA;AAAA,YACnC,CAAC,CAAA;AAAA,UACH;AAAA,SACF;AAAA,MACF;AACA,MAAA,IAAI,OAAO,mBAAA,EAAqB;AAC9B,QAAA,MAAM,WAAW,MAAA,CAAO,mBAAA;AACxB,QAAA,MAAA,CAAO,mBAAA,GAAsB;AAAA,UAC3B,IAAA,EAAM,CAAC,MAAA,KAA4B;AACjC,YAAA,MAAA,CAAO,uBAAuB,QAAQ,CAAA;AAAA,UACxC;AAAA,SACF;AAAA,MACF;AACA,MAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,QAAA,MAAM,MAAA,GAAS,CAAC,GAAG,MAAA,CAAO,MAAM,CAAA;AAChC,QAAA,MAAA,CAAO,MAAA,GAAS;AAAA,UACd,IAAA,EAAM,CAAC,MAAA,KAA4B;AACjC,YAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,KAAU;AACxB,cAAA,MAAA,CAAO,SAAS,KAAK,CAAA;AAAA,YACvB,CAAC,CAAA;AAAA,UACH;AAAA,SACF;AAAA,MACF;AACA,MAAA,IAAI,OAAO,GAAA,EAAK;AACd,QAAA,MAAM,GAAA,GAAM,CAAC,GAAG,MAAA,CAAO,GAAG,CAAA;AAC1B,QAAA,MAAA,CAAO,GAAA,GAAM;AAAA,UACX,IAAA,EAAM,CAAC,MAAA,KAA4B;AACjC,YAAA,MAAM,UAAA,GAAa,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,MAAM,CAAA;AAChD,YAAA,GAAA,CAAI,OAAA,CAAQ,CAACC,IAAAA,KAAQ;AACnB,cAAA,UAAA,CAAW,IAAIA,IAAG,CAAA;AAAA,YACpB,CAAC,CAAA;AAAA,UACH;AAAA,SACF;AAAA,MACF;AACA,MAAA,IAAI,OAAO,mBAAA,EAAqB;AAC9B,QAAA,MAAM,mBAAA,GAAsB,CAAC,GAAG,MAAA,CAAO,mBAAmB,CAAA;AAC1D,QAAA,MAAA,CAAO,mBAAA,GAAsB;AAAA,UAC3B,IAAA,EAAM,CAAC,MAAA,KAA4B;AACjC,YAAA,mBAAA,CAAoB,OAAA,CAAQ,CAAC,kBAAA,KAAuB;AAClD,cAAA,MAAA,CAAO,sBAAsB,kBAAkB,CAAA;AAAA,YACjD,CAAC,CAAA;AAAA,UACH;AAAA,SACF;AAAA,MACF;AACA,MAAA,IAAI,OAAO,SAAA,EAAW;AACpB,QAAA,MAAM,SAAA,GAAY,CAAC,GAAG,MAAA,CAAO,SAAS,CAAA;AACtC,QAAA,MAAA,CAAO,SAAA,GAAY;AAAA,UACjB,IAAA,EAAM,CAAC,MAAA,KAA4B;AACjC,YAAA,SAAA,CAAU,OAAA,CAAQ,CAAC,QAAA,KAAa;AAC9B,cAAA,MAAA,CAAO,YAAY,QAAQ,CAAA;AAAA,YAC7B,CAAC,CAAA;AAAA,UACH;AAAA,SACF;AAAA,MACF;AACA,MAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,QAAA,MAAM,MAAA,GAAS,EAAC,GAAG,MAAA,CAAO,MAAA,EAAM;AAChC,QAAA,MAAA,CAAO,MAAA,GAAS;AAAA,UACd,GAAG,MAAA;AAAA,UACH,IAAA,EAAM,CAAC,MAAA,KAA4B;AACjC,YAAA,IAAI,OAAO,gBAAA,EAAkB;AAC3B,cAAA,MAAA,CAAO,gBAAA,CAAiB,OAAA,CAAQ,CAAC,SAAA,KAAc;AAC7C,gBAAA,MAAA,CAAO,yBAAyB,SAAS,CAAA;AAAA,cAC3C,CAAC,CAAA;AAAA,YACH;AACA,YAAA,IAAI,OAAO,iBAAA,EAAmB;AAC5B,cAAA,MAAA,CAAO,iBAAA,CAAkB,OAAA,CAAQ,CAAC,SAAA,KAAc;AAC9C,gBAAA,MAAA,CAAO,0BAA0B,SAAS,CAAA;AAAA,cAC5C,CAAC,CAAA;AAAA,YACH;AAAA,UACF;AAAA,SACF;AAAA,MACF;AACA,MAAA,OAAO,MAAA;AAAA,IACT,CAAC,CAAA;AACD,IAAA,OAAOD,QAAAA;AAAA,EACT,CAAC,CAAA;AACH;AAEO,MAAM,iBAAA,GAAoB;AAE1B,SAAS,oBAAoB,MAAA,EAAa;AAC/C,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,iBAAA;AAAA,IACT,QAAA,EAAU,UAAU;AAAC,GACvB;AACF;AAEO,SAAS,yBAAA,CAA0B,MAAA,GAAc,EAAC,EAAG;AAC1D,EAAA,IAAI,CAAC,OAAO,gBAAA,EAAkB;AAC5B,IAAA,MAAA,CAAO,gBAAA,GAAmB;AAAA,MACxB,EAAA,EAAI,IAAA;AAAA,MACJ,IAAA,EAAM,MAAA;AAAA,MACN,IAAA,EAAM,MAAA;AAAA,MACN,KAAA,EAAO,OAAA;AAAA,MACP,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AACA,EAAA,OAAO,oBAAoB,MAAM,CAAA;AACnC;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpgjs/client",
3
- "version": "5.0.0-alpha.14",
3
+ "version": "5.0.0-alpha.15",
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.14",
26
- "@rpgjs/common": "5.0.0-alpha.14",
27
- "@rpgjs/server": "5.0.0-alpha.14",
25
+ "@rpgjs/client": "5.0.0-alpha.15",
26
+ "@rpgjs/common": "5.0.0-alpha.15",
27
+ "@rpgjs/server": "5.0.0-alpha.15",
28
28
  "@signe/di": "^2.4.6",
29
29
  "@signe/room": "^2.4.6",
30
30
  "@signe/sync": "^2.4.6",
package/src/Game/Map.ts CHANGED
@@ -6,7 +6,7 @@ import { RpgClientEvent } from "./Event";
6
6
  import { RpgClientEngine } from "../RpgClientEngine";
7
7
  import { inject } from "../core/inject";
8
8
 
9
- export class RpgClientMap extends RpgCommonMap<RpgClientPlayer> {
9
+ export class RpgClientMap extends RpgCommonMap<any> {
10
10
  engine: RpgClientEngine = inject(RpgClientEngine)
11
11
  @users(RpgClientPlayer) players = signal<Record<string, RpgClientPlayer>>({});
12
12
  @sync(RpgClientEvent) events = signal<Record<string, RpgClientEvent>>({});
@@ -20,4 +20,8 @@ export class RpgClientMap extends RpgCommonMap<RpgClientPlayer> {
20
20
  this.players.set({})
21
21
  this.events.set({})
22
22
  }
23
+
24
+ stepPredictionTick(): void {
25
+ this.forceSingleTick();
26
+ }
23
27
  }
@@ -1,7 +1,7 @@
1
1
  import { Hooks, ModulesToken, RpgCommonPlayer } from "@rpgjs/common";
2
2
  import { sync } from "@signe/sync";
3
3
  import { trigger, signal } from "canvasengine";
4
- import { Subscription } from "rxjs";
4
+ import { debounceTime, Subscription, throttleTime } from "rxjs";
5
5
  import { inject } from "../core/inject";
6
6
  import { RpgClientEngine } from "../RpgClientEngine";
7
7
 
@@ -12,16 +12,49 @@ export abstract class RpgClientObject extends RpgCommonPlayer {
12
12
  animationCurrentIndex = signal(0)
13
13
  animationIsPlaying = signal(false)
14
14
  _param = signal({})
15
+ frames: { x: number; y: number; ts: number }[] = []
15
16
 
16
17
  constructor() {
17
18
  super()
18
19
  this.hooks.callHooks("client-sprite-onInit", this).subscribe();
20
+
21
+ this._frames.observable.subscribe(({ items }) => {
22
+ if (!this.id) return;
23
+ //if (this.id == this.engine.playerIdSignal()!) return;
24
+ this.frames = [...this.frames, ...items]
25
+ })
26
+
27
+ this.engine.tick
28
+ .pipe(
29
+ //throttleTime(10)
30
+ )
31
+ .subscribe(() => {
32
+ const frame = this.frames.shift()
33
+ if (frame) {
34
+ const entity = this.engine.scene.getBody(this.id)
35
+ const isLocalPlayer = this.id === this.engine.playerIdSignal()
36
+ if (entity && !isLocalPlayer) {
37
+ const { x: oldX, y: oldY } = entity.position
38
+ const dt = 1 / 60 // Assume 60 FPS for now
39
+ const velocity = {
40
+ x: (frame.x - oldX) / dt,
41
+ y: (frame.y - oldY) / dt
42
+ }
43
+ entity.setVelocity(velocity)
44
+ }
45
+ this.engine.scene.setBodyPosition(this.id, frame.x, frame.y)
46
+ }
47
+ })
19
48
  }
20
49
 
21
50
  get hooks() {
22
51
  return inject<Hooks>(ModulesToken);
23
52
  }
24
-
53
+
54
+ get engine() {
55
+ return inject(RpgClientEngine)
56
+ }
57
+
25
58
  private animationSubscription?: Subscription
26
59
 
27
60
  flash(color: string, duration: number = 100) {
@@ -80,12 +113,12 @@ export abstract class RpgClientObject extends RpgCommonPlayer {
80
113
  this.animationIsPlaying.set(true);
81
114
  const previousAnimationName = this.animationName();
82
115
  this.animationCurrentIndex.set(0);
83
-
116
+
84
117
  // Clean up any existing subscription
85
118
  if (this.animationSubscription) {
86
119
  this.animationSubscription.unsubscribe();
87
120
  }
88
-
121
+
89
122
  this.animationSubscription = this.animationCurrentIndex.observable.subscribe(index => {
90
123
  if (index >= nbTimes) {
91
124
  this.animationCurrentIndex.set(0);
package/src/RpgClient.ts CHANGED
@@ -305,6 +305,46 @@ export interface RpgClient {
305
305
  * */
306
306
  spritesheets?: any[],
307
307
 
308
+ /**
309
+ * Resolver function for dynamically creating spritesheets
310
+ *
311
+ * This function is called when a spritesheet is requested but not found in the cache.
312
+ * It can be synchronous (returns directly) or asynchronous (returns a Promise).
313
+ * The resolved spritesheet is automatically cached for future use.
314
+ *
315
+ * ```ts
316
+ * import { defineModule, RpgClient } from '@rpgjs/client'
317
+ *
318
+ * defineModule<RpgClient>({
319
+ * spritesheetResolver: (id: string) => {
320
+ * // Synchronous resolver
321
+ * if (id === 'dynamic-sprite') {
322
+ * return {
323
+ * id: 'dynamic-sprite',
324
+ * image: 'path/to/image.png',
325
+ * framesWidth: 32,
326
+ * framesHeight: 32
327
+ * };
328
+ * }
329
+ * return undefined;
330
+ * }
331
+ * })
332
+ *
333
+ * // Or asynchronous resolver
334
+ * defineModule<RpgClient>({
335
+ * spritesheetResolver: async (id: string) => {
336
+ * const response = await fetch(`/api/spritesheets/${id}`);
337
+ * const data = await response.json();
338
+ * return data;
339
+ * }
340
+ * })
341
+ * ```
342
+ *
343
+ * @prop {(id: string) => any | Promise<any>} [spritesheetResolver]
344
+ * @memberof RpgClient
345
+ * */
346
+ spritesheetResolver?: (id: string) => any | Promise<any>,
347
+
308
348
  /**
309
349
  * Array containing the list of GUI components
310
350
  *