@rpgjs/client 5.0.0-alpha.13 → 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.
- package/dist/Game/Map.d.ts +2 -1
- package/dist/RpgClient.d.ts +39 -0
- package/dist/RpgClientEngine.d.ts +138 -2
- package/dist/index10.js +2 -3
- package/dist/index10.js.map +1 -1
- package/dist/index15.js +59 -17
- package/dist/index15.js.map +1 -1
- package/dist/index16.js.map +1 -1
- package/dist/index19.js.map +1 -1
- package/dist/index2.js +303 -3
- package/dist/index2.js.map +1 -1
- package/dist/index20.js +3 -0
- package/dist/index20.js.map +1 -1
- package/dist/index22.js +31 -31
- package/dist/index22.js.map +1 -1
- package/dist/index23.js +2 -2
- package/dist/index23.js.map +1 -1
- package/dist/index25.js +1 -2
- package/dist/index25.js.map +1 -1
- package/dist/index30.js.map +1 -1
- package/dist/index31.js.map +1 -1
- package/dist/index33.js +1 -1
- package/dist/index34.js +1 -1
- package/dist/index36.js +6 -4402
- package/dist/index36.js.map +1 -1
- package/dist/index37.js +3686 -170
- package/dist/index37.js.map +1 -1
- package/dist/index38.js +172 -486
- package/dist/index38.js.map +1 -1
- package/dist/index39.js +498 -71
- package/dist/index39.js.map +1 -1
- package/dist/index4.js +6 -1
- package/dist/index4.js.map +1 -1
- package/dist/index40.js +67 -10
- package/dist/index40.js.map +1 -1
- package/dist/index41.js +3 -93
- package/dist/index41.js.map +1 -1
- package/dist/index42.js +123 -0
- package/dist/index42.js.map +1 -0
- package/dist/index43.js +20 -0
- package/dist/index43.js.map +1 -0
- package/dist/index44.js +12 -0
- package/dist/index44.js.map +1 -0
- package/dist/index45.js +113 -0
- package/dist/index45.js.map +1 -0
- package/dist/index46.js +136 -0
- package/dist/index46.js.map +1 -0
- package/dist/index47.js +137 -0
- package/dist/index47.js.map +1 -0
- package/dist/index48.js +112 -0
- package/dist/index48.js.map +1 -0
- package/dist/index49.js +9 -0
- package/dist/index49.js.map +1 -0
- package/dist/index8.js +8 -0
- package/dist/index8.js.map +1 -1
- package/dist/services/mmorpg.d.ts +1 -0
- package/package.json +8 -8
- package/src/Game/Map.ts +5 -1
- package/src/Game/Object.ts +37 -4
- package/src/RpgClient.ts +40 -0
- package/src/RpgClientEngine.ts +374 -11
- package/src/components/animations/animation.ce +1 -2
- package/src/components/character.ce +81 -20
- package/src/components/gui/dialogbox/index.ce +1 -2
- package/src/module.ts +8 -0
- package/src/services/mmorpg.ts +7 -1
|
@@ -7,10 +7,9 @@
|
|
|
7
7
|
const { x, y, animationName, graphic, onFinish } = defineProps();
|
|
8
8
|
|
|
9
9
|
const client = inject(RpgClientEngine);
|
|
10
|
-
const spritesheets = client.spritesheets;
|
|
11
10
|
|
|
12
11
|
const sheet = {
|
|
13
|
-
definition:
|
|
12
|
+
definition: client.getSpriteSheet(graphic()),
|
|
14
13
|
playing: animationName() ?? 'default',
|
|
15
14
|
onFinish
|
|
16
15
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<Container x y zIndex={y} viewportFollow={isMe} controls onBeforeDestroy>
|
|
1
|
+
<Container x={smoothX} y={smoothY} zIndex={y} viewportFollow={isMe} controls onBeforeDestroy visible>
|
|
2
2
|
@for (component of componentsBehind) {
|
|
3
3
|
<Container>
|
|
4
4
|
<component object />
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
</Container>
|
|
19
19
|
|
|
20
20
|
<script>
|
|
21
|
-
import { signal, effect, mount, computed, tick } from "canvasengine";
|
|
22
|
-
import { lastValueFrom } from "rxjs";
|
|
21
|
+
import { signal, effect, mount, computed, tick, animatedSignal } from "canvasengine";
|
|
22
|
+
import { lastValueFrom, combineLatest, pairwise, filter, map, startWith } from "rxjs";
|
|
23
23
|
import { Particle } from "@canvasengine/presets";
|
|
24
24
|
import { GameEngineToken, ModulesToken } from "@rpgjs/common";
|
|
25
25
|
import { RpgClientEngine } from "../RpgClientEngine";
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
import Hit from "./effects/hit.ce";
|
|
29
29
|
|
|
30
30
|
const { object, id } = defineProps();
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
const client = inject(RpgClientEngine);
|
|
33
33
|
const hooks = inject(ModulesToken);
|
|
34
34
|
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
emitParticleTrigger,
|
|
49
49
|
particleName,
|
|
50
50
|
graphics,
|
|
51
|
-
hitbox
|
|
51
|
+
hitbox,
|
|
52
|
+
isConnected,
|
|
52
53
|
} = object;
|
|
53
54
|
|
|
54
55
|
const particleSettings = client.particleSettings;
|
|
@@ -56,6 +57,13 @@
|
|
|
56
57
|
const canControls = () => isMe() && object.canMove()
|
|
57
58
|
const keyboardControls = client.globalConfig.keyboardControls;
|
|
58
59
|
|
|
60
|
+
const visible = computed(() => {
|
|
61
|
+
if (object.type === 'event') {
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
return isConnected()
|
|
65
|
+
});
|
|
66
|
+
|
|
59
67
|
const controls = signal({
|
|
60
68
|
down: {
|
|
61
69
|
repeat: true,
|
|
@@ -98,10 +106,28 @@
|
|
|
98
106
|
},
|
|
99
107
|
});
|
|
100
108
|
|
|
109
|
+
const smoothX = animatedSignal(x(), {
|
|
110
|
+
duration: isMe() ? 0 : 0
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const smoothY = animatedSignal(y(), {
|
|
114
|
+
duration: isMe() ? 0 : 0,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const realAnimationName = signal(animationName());
|
|
118
|
+
|
|
119
|
+
const xSubscription = x.observable.subscribe((value) => {
|
|
120
|
+
smoothX.set(value);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const ySubscription = y.observable.subscribe((value) => {
|
|
124
|
+
smoothY.set(value);
|
|
125
|
+
});
|
|
126
|
+
|
|
101
127
|
const sheet = (graphicId) => {
|
|
102
128
|
return {
|
|
103
|
-
definition:
|
|
104
|
-
playing:
|
|
129
|
+
definition: client.getSpriteSheet(graphicId),
|
|
130
|
+
playing: realAnimationName,
|
|
105
131
|
params: {
|
|
106
132
|
direction
|
|
107
133
|
},
|
|
@@ -111,27 +137,62 @@
|
|
|
111
137
|
};
|
|
112
138
|
}
|
|
113
139
|
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
140
|
+
// Combine animation change detection with movement state from smoothX/smoothY
|
|
141
|
+
const movementAnimations = ['walk', 'stand'];
|
|
142
|
+
const epsilon = 0; // movement threshold to consider the easing still running
|
|
143
|
+
|
|
144
|
+
const stateX$ = smoothX.animatedState.observable;
|
|
145
|
+
const stateY$ = smoothY.animatedState.observable;
|
|
146
|
+
const animationName$ = animationName.observable;
|
|
147
|
+
|
|
148
|
+
const moving$ = combineLatest([stateX$, stateY$]).pipe(
|
|
149
|
+
map(([sx, sy]) => {
|
|
150
|
+
const xFinished = Math.abs(sx.value.current - sx.value.end) <= epsilon;
|
|
151
|
+
const yFinished = Math.abs(sy.value.current - sy.value.end) <= epsilon;
|
|
152
|
+
return !xFinished || !yFinished; // moving if X or Y is not finished
|
|
153
|
+
}),
|
|
154
|
+
startWith(false)
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
const animationChange$ = animationName$.pipe(
|
|
158
|
+
startWith(animationName()),
|
|
159
|
+
pairwise(),
|
|
160
|
+
filter(([prev, curr]) => prev !== curr)
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const animationMovementSubscription = combineLatest([animationChange$, moving$]).subscribe(([[prev, curr], isMoving]) => {
|
|
164
|
+
if (curr == 'stand' && !isMoving) {
|
|
165
|
+
realAnimationName.set(curr);
|
|
166
|
+
}
|
|
167
|
+
else if (curr == 'walk' && isMoving) {
|
|
168
|
+
realAnimationName.set(curr);
|
|
169
|
+
}
|
|
170
|
+
else if (!movementAnimations.includes(curr)) {
|
|
171
|
+
realAnimationName.set(curr);
|
|
172
|
+
}
|
|
173
|
+
if (!isMoving && object.animationIsPlaying && object.animationIsPlaying()) {
|
|
174
|
+
if (movementAnimations.includes(curr)) {
|
|
124
175
|
if (typeof object.resetAnimationState === 'function') {
|
|
125
176
|
object.resetAnimationState();
|
|
126
177
|
}
|
|
127
178
|
}
|
|
128
179
|
}
|
|
129
|
-
|
|
130
|
-
previousAnimationName = currentAnimationName;
|
|
131
|
-
|
|
132
180
|
});
|
|
133
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Cleanup subscriptions and call hooks before sprite destruction.
|
|
184
|
+
*
|
|
185
|
+
* # Design
|
|
186
|
+
* - Prevent memory leaks by unsubscribing from all local subscriptions created in this component.
|
|
187
|
+
* - Execute destruction hooks to notify modules and scene map of sprite removal.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* await onBeforeDestroy();
|
|
191
|
+
*/
|
|
134
192
|
const onBeforeDestroy = async () => {
|
|
193
|
+
animationMovementSubscription.unsubscribe();
|
|
194
|
+
xSubscription.unsubscribe();
|
|
195
|
+
ySubscription.unsubscribe();
|
|
135
196
|
await lastValueFrom(hooks.callHooks("client-sprite-onDestroy", object))
|
|
136
197
|
await lastValueFrom(hooks.callHooks("client-sceneMap-onRemoveSprite", client.sceneMap, object))
|
|
137
198
|
}
|
|
@@ -78,7 +78,6 @@
|
|
|
78
78
|
}
|
|
79
79
|
const dialogBoxTypewriterSound = client.globalConfig?.box?.sounds?.typewriter
|
|
80
80
|
|
|
81
|
-
const spritesheets = client.spritesheets;
|
|
82
81
|
const sounds = client.sounds;
|
|
83
82
|
|
|
84
83
|
client.stopProcessingInput = true;
|
|
@@ -140,7 +139,7 @@
|
|
|
140
139
|
|
|
141
140
|
const faceSheet = (graphicId, animationName) => {
|
|
142
141
|
return {
|
|
143
|
-
definition:
|
|
142
|
+
definition: client.getSpriteSheet(graphicId),
|
|
144
143
|
playing: animationName,
|
|
145
144
|
};
|
|
146
145
|
}
|
package/src/module.ts
CHANGED
|
@@ -22,6 +22,14 @@ export function provideClientModules(modules: RpgClient[]) {
|
|
|
22
22
|
},
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
+
if (module.spritesheetResolver) {
|
|
26
|
+
const resolver = module.spritesheetResolver;
|
|
27
|
+
module.spritesheetResolver = {
|
|
28
|
+
load: (engine: RpgClientEngine) => {
|
|
29
|
+
engine.setSpritesheetResolver(resolver);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
25
33
|
if (module.sounds) {
|
|
26
34
|
const sounds = [...module.sounds];
|
|
27
35
|
module.sounds = {
|
package/src/services/mmorpg.ts
CHANGED
|
@@ -10,10 +10,14 @@ interface MmorpgOptions {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
class BridgeWebsocket extends AbstractWebsocket {
|
|
13
|
-
|
|
13
|
+
private socket: any;
|
|
14
|
+
private privateId: string;
|
|
14
15
|
|
|
15
16
|
constructor(protected context: Context, private options: MmorpgOptions = {}) {
|
|
16
17
|
super(context);
|
|
18
|
+
const id = localStorage.getItem("rpgjs-user-id") || crypto.randomUUID()
|
|
19
|
+
localStorage.setItem("rpgjs-user-id", id)
|
|
20
|
+
this.privateId = id
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
async connection(listeners?: (data: any) => void) {
|
|
@@ -25,6 +29,7 @@ class BridgeWebsocket extends AbstractWebsocket {
|
|
|
25
29
|
this.socket = await connectionRoom({
|
|
26
30
|
host: this.options.host || window.location.host,
|
|
27
31
|
room: "lobby-1",
|
|
32
|
+
id: this.privateId
|
|
28
33
|
}, instance)
|
|
29
34
|
|
|
30
35
|
listeners?.(this.socket)
|
|
@@ -45,6 +50,7 @@ class BridgeWebsocket extends AbstractWebsocket {
|
|
|
45
50
|
updateProperties({ room }: { room: any }) {
|
|
46
51
|
this.socket.conn.updateProperties({
|
|
47
52
|
room: room,
|
|
53
|
+
id: this.privateId,
|
|
48
54
|
host: this.options.host
|
|
49
55
|
})
|
|
50
56
|
}
|