@rpgjs/common 5.0.0-alpha.42 → 5.0.0-alpha.44

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.
@@ -309,6 +309,8 @@ export declare abstract class RpgCommonMap<T extends RpgCommonPlayer> {
309
309
  private createCharacterHitbox;
310
310
  private updateCharacterHitbox;
311
311
  private resolveNumeric;
312
+ private bindCharacterSignalSync;
313
+ private unbindCharacterSignalSync;
312
314
  private shouldDisableCharacterCollisions;
313
315
  private resolvePhysicsEntityKind;
314
316
  protected emitPhysicsInit(_context: MapPhysicsInitContext): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpgjs/common",
3
- "version": "5.0.0-alpha.42",
3
+ "version": "5.0.0-alpha.44",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "publishConfig": {
@@ -11,7 +11,7 @@
11
11
  "license": "MIT",
12
12
  "description": "",
13
13
  "dependencies": {
14
- "@rpgjs/physic": "5.0.0-alpha.42",
14
+ "@rpgjs/physic": "5.0.0-alpha.44",
15
15
  "@signe/di": "^2.8.3",
16
16
  "@signe/reactive": "^2.8.3",
17
17
  "@signe/sync": "^2.8.3",
package/src/rooms/Map.ts CHANGED
@@ -281,6 +281,7 @@ export abstract class RpgCommonMap<T extends RpgCommonPlayer> {
281
281
  kind: this.resolvePhysicsEntityKind(owner, entity.uuid),
282
282
  });
283
283
  }
284
+ this.unbindCharacterSignalSync(entity);
284
285
  this.physic.removeEntity(entity);
285
286
  }
286
287
 
@@ -644,6 +645,7 @@ export abstract class RpgCommonMap<T extends RpgCommonPlayer> {
644
645
  // Rebind owner when the player instance is restored/replaced (e.g. map transfer).
645
646
  // Position sync callbacks read entity.owner at runtime.
646
647
  (existingEntity as any).owner = owner;
648
+ this.bindCharacterSignalSync(existingEntity, owner);
647
649
  this.updateCharacterHitbox(owner);
648
650
  return;
649
651
  }
@@ -679,6 +681,7 @@ export abstract class RpgCommonMap<T extends RpgCommonPlayer> {
679
681
  // Rebind owner on every update to keep physics callbacks attached to the
680
682
  // current player instance after room/session transfers.
681
683
  (entity as any).owner = owner;
684
+ this.bindCharacterSignalSync(entity, owner);
682
685
 
683
686
  const hitbox = typeof owner.hitbox === "function" ? owner.hitbox() : owner.hitbox;
684
687
  const width = hitbox?.w ?? 32;
@@ -703,6 +706,60 @@ export abstract class RpgCommonMap<T extends RpgCommonPlayer> {
703
706
  return fallback;
704
707
  }
705
708
 
709
+ private bindCharacterSignalSync(entity: Entity, owner: any): void {
710
+ const entityAny = entity as any;
711
+ if (
712
+ entityAny.__rpgSignalSyncOwner === owner &&
713
+ typeof entityAny.__rpgSignalSyncUnsubscribe === "function"
714
+ ) {
715
+ return;
716
+ }
717
+
718
+ this.unbindCharacterSignalSync(entity);
719
+ entityAny.__rpgSignalSyncOwner = owner;
720
+
721
+ const subscriptions: Subscription[] = [];
722
+ entityAny.__rpgSignalSyncUnsubscribe = () => {
723
+ subscriptions.forEach((subscription) => subscription.unsubscribe());
724
+ delete entityAny.__rpgSignalSyncUnsubscribe;
725
+ delete entityAny.__rpgSignalSyncOwner;
726
+ };
727
+
728
+ const syncFromSignals = () => {
729
+ if (this.isPhysicsSyncingSignals) {
730
+ return;
731
+ }
732
+ const currentOwner = entityAny.owner;
733
+ if (!currentOwner?.id || currentOwner.id !== entity.uuid) {
734
+ return;
735
+ }
736
+ this.updateCharacterHitbox(currentOwner);
737
+ };
738
+
739
+ const subscribeSignal = (signalLike: any) => {
740
+ const observable = signalLike?.observable;
741
+ if (!observable || typeof observable.subscribe !== "function") {
742
+ return;
743
+ }
744
+ subscriptions.push(observable.subscribe(() => syncFromSignals()));
745
+ };
746
+
747
+ subscribeSignal(owner.x);
748
+ subscribeSignal(owner.y);
749
+ subscribeSignal(owner.hitbox);
750
+ subscribeSignal(owner._through);
751
+ }
752
+
753
+ private unbindCharacterSignalSync(entity: Entity): void {
754
+ const entityAny = entity as any;
755
+ const unsubscribe = entityAny.__rpgSignalSyncUnsubscribe;
756
+ if (typeof unsubscribe === "function") {
757
+ unsubscribe();
758
+ return;
759
+ }
760
+ delete entityAny.__rpgSignalSyncOwner;
761
+ }
762
+
706
763
  private shouldDisableCharacterCollisions(owner: any): boolean {
707
764
  if (typeof owner._through === "function") {
708
765
  try {
@@ -1152,6 +1209,7 @@ export abstract class RpgCommonMap<T extends RpgCommonPlayer> {
1152
1209
 
1153
1210
  // Store owner reference directly on entity for syncing positions
1154
1211
  (entity as any).owner = owner;
1212
+ this.bindCharacterSignalSync(entity, owner);
1155
1213
 
1156
1214
  entity.onDirectionChange(({ cardinalDirection }) => {
1157
1215
  // hack to prevent direction in client side
@@ -1219,14 +1277,16 @@ export abstract class RpgCommonMap<T extends RpgCommonPlayer> {
1219
1277
  const topLeftY = y - entityHeight / 2;
1220
1278
  let changed = false;
1221
1279
 
1222
- if (typeof currentOwner.x === "function" && typeof currentOwner.x.set === "function") {
1223
- currentOwner.x.set(Math.round(topLeftX));
1224
- changed = true;
1225
- }
1226
- if (typeof currentOwner.y === "function" && typeof currentOwner.y.set === "function") {
1227
- currentOwner.y.set(Math.round(topLeftY));
1228
- changed = true;
1229
- }
1280
+ this.withPhysicsSync(() => {
1281
+ if (typeof currentOwner.x === "function" && typeof currentOwner.x.set === "function") {
1282
+ currentOwner.x.set(Math.round(topLeftX));
1283
+ changed = true;
1284
+ }
1285
+ if (typeof currentOwner.y === "function" && typeof currentOwner.y.set === "function") {
1286
+ currentOwner.y.set(Math.round(topLeftY));
1287
+ changed = true;
1288
+ }
1289
+ });
1230
1290
  if (changed) {
1231
1291
  currentOwner.applyFrames?.();
1232
1292
  }
@@ -1374,6 +1434,7 @@ export abstract class RpgCommonMap<T extends RpgCommonPlayer> {
1374
1434
  if (!entity) {
1375
1435
  return false;
1376
1436
  }
1437
+ this.unbindCharacterSignalSync(entity);
1377
1438
  const resolvedOwner = owner ?? (entity as any).owner;
1378
1439
  if (resolvedOwner) {
1379
1440
  this.emitPhysicsEntityRemove({