@rpgjs/server 5.0.0-alpha.16 → 5.0.0-alpha.18
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/Player/ComponentManager.d.ts +95 -32
- package/dist/Player/Components.d.ts +345 -0
- package/dist/Player/Player.d.ts +133 -12
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1996 -311
- package/dist/index.js.map +1 -1
- package/dist/rooms/map.d.ts +264 -7
- package/package.json +3 -3
- package/src/Player/ComponentManager.ts +394 -32
- package/src/Player/Components.ts +380 -0
- package/src/Player/MoveManager.ts +1 -1
- package/src/Player/Player.ts +387 -49
- package/src/index.ts +3 -1
- package/src/rooms/map.ts +488 -22
package/dist/index.js
CHANGED
|
@@ -11298,6 +11298,11 @@ class RpgCommonPlayer {
|
|
|
11298
11298
|
this._throughEvent = signal(false);
|
|
11299
11299
|
this._frequency = signal(0);
|
|
11300
11300
|
this._frames = signal([]);
|
|
11301
|
+
this.componentsTop = signal(null);
|
|
11302
|
+
this.componentsBottom = signal(null);
|
|
11303
|
+
this.componentsCenter = signal(null);
|
|
11304
|
+
this.componentsLeft = signal(null);
|
|
11305
|
+
this.componentsRight = signal(null);
|
|
11301
11306
|
this.isConnected = signal(false);
|
|
11302
11307
|
// Store intended movement direction (not synced, only used locally)
|
|
11303
11308
|
this._intendedDirection = null;
|
|
@@ -11349,10 +11354,10 @@ __decorateClass$3([
|
|
|
11349
11354
|
sync()
|
|
11350
11355
|
], RpgCommonPlayer.prototype, "type");
|
|
11351
11356
|
__decorateClass$3([
|
|
11352
|
-
|
|
11357
|
+
sync()
|
|
11353
11358
|
], RpgCommonPlayer.prototype, "x");
|
|
11354
11359
|
__decorateClass$3([
|
|
11355
|
-
|
|
11360
|
+
sync()
|
|
11356
11361
|
], RpgCommonPlayer.prototype, "y");
|
|
11357
11362
|
__decorateClass$3([
|
|
11358
11363
|
sync()
|
|
@@ -11423,11 +11428,95 @@ __decorateClass$3([
|
|
|
11423
11428
|
__decorateClass$3([
|
|
11424
11429
|
sync()
|
|
11425
11430
|
], RpgCommonPlayer.prototype, "_frames");
|
|
11431
|
+
__decorateClass$3([
|
|
11432
|
+
sync()
|
|
11433
|
+
], RpgCommonPlayer.prototype, "componentsTop");
|
|
11434
|
+
__decorateClass$3([
|
|
11435
|
+
sync()
|
|
11436
|
+
], RpgCommonPlayer.prototype, "componentsBottom");
|
|
11437
|
+
__decorateClass$3([
|
|
11438
|
+
sync()
|
|
11439
|
+
], RpgCommonPlayer.prototype, "componentsCenter");
|
|
11440
|
+
__decorateClass$3([
|
|
11441
|
+
sync()
|
|
11442
|
+
], RpgCommonPlayer.prototype, "componentsLeft");
|
|
11443
|
+
__decorateClass$3([
|
|
11444
|
+
sync()
|
|
11445
|
+
], RpgCommonPlayer.prototype, "componentsRight");
|
|
11426
11446
|
__decorateClass$3([
|
|
11427
11447
|
connected()
|
|
11428
11448
|
], RpgCommonPlayer.prototype, "isConnected");
|
|
11429
11449
|
|
|
11430
|
-
|
|
11450
|
+
class RpgShape {
|
|
11451
|
+
/**
|
|
11452
|
+
* Creates a new RpgShape instance
|
|
11453
|
+
*
|
|
11454
|
+
* @param config - Shape configuration
|
|
11455
|
+
*/
|
|
11456
|
+
constructor(config) {
|
|
11457
|
+
this.name = config.name;
|
|
11458
|
+
this.positioning = config.positioning;
|
|
11459
|
+
this.width = config.width;
|
|
11460
|
+
this.height = config.height;
|
|
11461
|
+
this.x = config.x;
|
|
11462
|
+
this.y = config.y;
|
|
11463
|
+
this.properties = config.properties;
|
|
11464
|
+
this._playerOwner = config.playerOwner;
|
|
11465
|
+
this._physicZoneId = config.physicZoneId;
|
|
11466
|
+
this._map = config.map;
|
|
11467
|
+
}
|
|
11468
|
+
/**
|
|
11469
|
+
* Checks if a player is currently inside this shape
|
|
11470
|
+
*
|
|
11471
|
+
* @param player - The player to check
|
|
11472
|
+
* @returns True if the player is inside the shape
|
|
11473
|
+
*
|
|
11474
|
+
* @example
|
|
11475
|
+
* ```ts
|
|
11476
|
+
* const shape = player.attachShape("detection", { radius: 100 });
|
|
11477
|
+
* if (shape.playerIsIn(otherPlayer)) {
|
|
11478
|
+
* console.log("Player detected in zone");
|
|
11479
|
+
* }
|
|
11480
|
+
* ```
|
|
11481
|
+
*/
|
|
11482
|
+
playerIsIn(player) {
|
|
11483
|
+
if (!this._map) return false;
|
|
11484
|
+
const zoneManager = this._map.physic.getZoneManager();
|
|
11485
|
+
const entities = zoneManager.getEntitiesInZone(this._physicZoneId);
|
|
11486
|
+
if (!entities || entities.length === 0) return false;
|
|
11487
|
+
const playerEntity = this._map.physic.getEntityByUUID(player.id);
|
|
11488
|
+
if (!playerEntity) return false;
|
|
11489
|
+
return entities.some((entity) => entity.uuid === playerEntity.uuid);
|
|
11490
|
+
}
|
|
11491
|
+
/**
|
|
11492
|
+
* Gets the player that owns this shape
|
|
11493
|
+
*
|
|
11494
|
+
* Returns the player on which `attachShape()` was called to create this shape.
|
|
11495
|
+
*
|
|
11496
|
+
* @returns The player owner or undefined if not available
|
|
11497
|
+
*
|
|
11498
|
+
* @example
|
|
11499
|
+
* ```ts
|
|
11500
|
+
* const shape = player.attachShape("vision", { radius: 150 });
|
|
11501
|
+
* const owner = shape.getPlayerOwner();
|
|
11502
|
+
* console.log(owner?.name); // Player's name
|
|
11503
|
+
* ```
|
|
11504
|
+
*/
|
|
11505
|
+
getPlayerOwner() {
|
|
11506
|
+
return this._playerOwner;
|
|
11507
|
+
}
|
|
11508
|
+
/**
|
|
11509
|
+
* Updates the shape's position
|
|
11510
|
+
*
|
|
11511
|
+
* @internal
|
|
11512
|
+
*/
|
|
11513
|
+
_updatePosition(x, y) {
|
|
11514
|
+
this.x = x;
|
|
11515
|
+
this.y = y;
|
|
11516
|
+
}
|
|
11517
|
+
}
|
|
11518
|
+
|
|
11519
|
+
const _Vector2$1 = class _Vector2 {
|
|
11431
11520
|
/**
|
|
11432
11521
|
* Creates a new Vector2
|
|
11433
11522
|
*
|
|
@@ -11697,10 +11786,10 @@ const _Vector2 = class _Vector2 {
|
|
|
11697
11786
|
return `Vector2(${this.x}, ${this.y})`;
|
|
11698
11787
|
}
|
|
11699
11788
|
};
|
|
11700
|
-
_Vector2.ZERO = new _Vector2(0, 0);
|
|
11701
|
-
_Vector2.UNIT_X = new _Vector2(1, 0);
|
|
11702
|
-
_Vector2.UNIT_Y = new _Vector2(0, 1);
|
|
11703
|
-
let Vector2 = _Vector2;
|
|
11789
|
+
_Vector2$1.ZERO = new _Vector2$1(0, 0);
|
|
11790
|
+
_Vector2$1.UNIT_X = new _Vector2$1(1, 0);
|
|
11791
|
+
_Vector2$1.UNIT_Y = new _Vector2$1(0, 1);
|
|
11792
|
+
let Vector2$1 = _Vector2$1;
|
|
11704
11793
|
|
|
11705
11794
|
class AABB {
|
|
11706
11795
|
/**
|
|
@@ -11790,7 +11879,7 @@ class AABB {
|
|
|
11790
11879
|
* @returns Center point
|
|
11791
11880
|
*/
|
|
11792
11881
|
getCenter() {
|
|
11793
|
-
return new Vector2(
|
|
11882
|
+
return new Vector2$1(
|
|
11794
11883
|
(this.minX + this.maxX) / 2,
|
|
11795
11884
|
(this.minY + this.maxY) / 2
|
|
11796
11885
|
);
|
|
@@ -11968,20 +12057,20 @@ class AABB {
|
|
|
11968
12057
|
* @returns Clamped point
|
|
11969
12058
|
*/
|
|
11970
12059
|
clamp(point) {
|
|
11971
|
-
return new Vector2(
|
|
12060
|
+
return new Vector2$1(
|
|
11972
12061
|
Math.max(this.minX, Math.min(this.maxX, point.x)),
|
|
11973
12062
|
Math.max(this.minY, Math.min(this.maxY, point.y))
|
|
11974
12063
|
);
|
|
11975
12064
|
}
|
|
11976
12065
|
}
|
|
11977
12066
|
|
|
11978
|
-
var EntityState = /* @__PURE__ */ ((EntityState2) => {
|
|
12067
|
+
var EntityState$1 = /* @__PURE__ */ ((EntityState2) => {
|
|
11979
12068
|
EntityState2[EntityState2["Static"] = 1] = "Static";
|
|
11980
12069
|
EntityState2[EntityState2["Dynamic"] = 2] = "Dynamic";
|
|
11981
12070
|
EntityState2[EntityState2["Sleeping"] = 4] = "Sleeping";
|
|
11982
12071
|
EntityState2[EntityState2["Kinematic"] = 8] = "Kinematic";
|
|
11983
12072
|
return EntityState2;
|
|
11984
|
-
})(EntityState || {});
|
|
12073
|
+
})(EntityState$1 || {});
|
|
11985
12074
|
|
|
11986
12075
|
function generateUUID() {
|
|
11987
12076
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
@@ -12004,20 +12093,20 @@ class Entity {
|
|
|
12004
12093
|
constructor(config = {}) {
|
|
12005
12094
|
this.lastCardinalDirection = "idle";
|
|
12006
12095
|
this.uuid = config.uuid ?? generateUUID();
|
|
12007
|
-
if (config.position instanceof Vector2) {
|
|
12096
|
+
if (config.position instanceof Vector2$1) {
|
|
12008
12097
|
this.position = config.position.clone();
|
|
12009
12098
|
} else if (config.position) {
|
|
12010
|
-
this.position = new Vector2(config.position.x, config.position.y);
|
|
12099
|
+
this.position = new Vector2$1(config.position.x, config.position.y);
|
|
12011
12100
|
} else {
|
|
12012
|
-
this.position = new Vector2(0, 0);
|
|
12101
|
+
this.position = new Vector2$1(0, 0);
|
|
12013
12102
|
}
|
|
12014
|
-
this.currentTile = new Vector2(0, 0);
|
|
12015
|
-
if (config.velocity instanceof Vector2) {
|
|
12103
|
+
this.currentTile = new Vector2$1(0, 0);
|
|
12104
|
+
if (config.velocity instanceof Vector2$1) {
|
|
12016
12105
|
this.velocity = config.velocity.clone();
|
|
12017
12106
|
} else if (config.velocity) {
|
|
12018
|
-
this.velocity = new Vector2(config.velocity.x, config.velocity.y);
|
|
12107
|
+
this.velocity = new Vector2$1(config.velocity.x, config.velocity.y);
|
|
12019
12108
|
} else {
|
|
12020
|
-
this.velocity = new Vector2(0, 0);
|
|
12109
|
+
this.velocity = new Vector2$1(0, 0);
|
|
12021
12110
|
}
|
|
12022
12111
|
this.rotation = config.rotation ?? 0;
|
|
12023
12112
|
this.angularVelocity = config.angularVelocity ?? 0;
|
|
@@ -12030,14 +12119,14 @@ class Entity {
|
|
|
12030
12119
|
this.capsule = config.capsule;
|
|
12031
12120
|
}
|
|
12032
12121
|
this.continuous = config.continuous ?? false;
|
|
12033
|
-
this.state = config.state ?? EntityState.Dynamic;
|
|
12122
|
+
this.state = config.state ?? EntityState$1.Dynamic;
|
|
12034
12123
|
this.restitution = config.restitution ?? 0.2;
|
|
12035
12124
|
this.friction = config.friction ?? 0.3;
|
|
12036
12125
|
this.linearDamping = config.linearDamping ?? 0.01;
|
|
12037
12126
|
this.angularDamping = config.angularDamping ?? 0.01;
|
|
12038
12127
|
this.maxLinearVelocity = config.maxLinearVelocity ?? Infinity;
|
|
12039
12128
|
this.maxAngularVelocity = config.maxAngularVelocity ?? Infinity;
|
|
12040
|
-
this.force = new Vector2(0, 0);
|
|
12129
|
+
this.force = new Vector2$1(0, 0);
|
|
12041
12130
|
this.torque = 0;
|
|
12042
12131
|
this.collisionMask = config.collisionMask ?? 4294967295;
|
|
12043
12132
|
this.collisionCategory = config.collisionCategory ?? 1;
|
|
@@ -12172,7 +12261,7 @@ class Entity {
|
|
|
12172
12261
|
*/
|
|
12173
12262
|
notifyDirectionChange() {
|
|
12174
12263
|
const isMoving = this.velocity.lengthSquared() > DIRECTION_CHANGE_THRESHOLD_SQ;
|
|
12175
|
-
const direction = isMoving ? this.velocity.clone().normalize() : new Vector2(0, 0);
|
|
12264
|
+
const direction = isMoving ? this.velocity.clone().normalize() : new Vector2$1(0, 0);
|
|
12176
12265
|
const cardinalDirection = this.computeCardinalDirection(direction);
|
|
12177
12266
|
if (cardinalDirection !== "idle") {
|
|
12178
12267
|
this.lastCardinalDirection = cardinalDirection;
|
|
@@ -12415,7 +12504,7 @@ class Entity {
|
|
|
12415
12504
|
* @returns This entity for chaining
|
|
12416
12505
|
*/
|
|
12417
12506
|
teleport(position) {
|
|
12418
|
-
if (position instanceof Vector2) {
|
|
12507
|
+
if (position instanceof Vector2$1) {
|
|
12419
12508
|
this.position.copyFrom(position);
|
|
12420
12509
|
} else {
|
|
12421
12510
|
this.position.set(position.x, position.y);
|
|
@@ -12432,14 +12521,14 @@ class Entity {
|
|
|
12432
12521
|
*/
|
|
12433
12522
|
setVelocity(velocity) {
|
|
12434
12523
|
const oldVelocity = this.velocity.clone();
|
|
12435
|
-
if (velocity instanceof Vector2) {
|
|
12524
|
+
if (velocity instanceof Vector2$1) {
|
|
12436
12525
|
this.velocity.copyFrom(velocity);
|
|
12437
12526
|
} else {
|
|
12438
12527
|
this.velocity.set(velocity.x, velocity.y);
|
|
12439
12528
|
}
|
|
12440
12529
|
this.wakeUp();
|
|
12441
|
-
const oldDirection = oldVelocity.lengthSquared() > MOVEMENT_EPSILON_SQ ? oldVelocity.clone().normalize() : new Vector2(0, 0);
|
|
12442
|
-
const newDirection = this.velocity.lengthSquared() > MOVEMENT_EPSILON_SQ ? this.velocity.clone().normalize() : new Vector2(0, 0);
|
|
12530
|
+
const oldDirection = oldVelocity.lengthSquared() > MOVEMENT_EPSILON_SQ ? oldVelocity.clone().normalize() : new Vector2$1(0, 0);
|
|
12531
|
+
const newDirection = this.velocity.lengthSquared() > MOVEMENT_EPSILON_SQ ? this.velocity.clone().normalize() : new Vector2$1(0, 0);
|
|
12443
12532
|
const oldCardinal = this.computeCardinalDirection(oldDirection);
|
|
12444
12533
|
const newCardinal = this.computeCardinalDirection(newDirection);
|
|
12445
12534
|
if (oldCardinal !== newCardinal || Math.abs(oldDirection.dot(newDirection) - 1) > 0.01) {
|
|
@@ -12454,7 +12543,7 @@ class Entity {
|
|
|
12454
12543
|
* @returns This entity for chaining
|
|
12455
12544
|
*/
|
|
12456
12545
|
freeze() {
|
|
12457
|
-
this.state = EntityState.Static;
|
|
12546
|
+
this.state = EntityState$1.Static;
|
|
12458
12547
|
this.velocity.set(0, 0);
|
|
12459
12548
|
this.angularVelocity = 0;
|
|
12460
12549
|
this.force.set(0, 0);
|
|
@@ -12469,7 +12558,7 @@ class Entity {
|
|
|
12469
12558
|
*/
|
|
12470
12559
|
unfreeze() {
|
|
12471
12560
|
if (this.mass > 0) {
|
|
12472
|
-
this.state = EntityState.Dynamic;
|
|
12561
|
+
this.state = EntityState$1.Dynamic;
|
|
12473
12562
|
}
|
|
12474
12563
|
return this;
|
|
12475
12564
|
}
|
|
@@ -12480,7 +12569,7 @@ class Entity {
|
|
|
12480
12569
|
*/
|
|
12481
12570
|
sleep() {
|
|
12482
12571
|
if (!this.isStatic()) {
|
|
12483
|
-
this.state |= EntityState.Sleeping;
|
|
12572
|
+
this.state |= EntityState$1.Sleeping;
|
|
12484
12573
|
this.velocity.set(0, 0);
|
|
12485
12574
|
this.angularVelocity = 0;
|
|
12486
12575
|
this.force.set(0, 0);
|
|
@@ -12495,7 +12584,7 @@ class Entity {
|
|
|
12495
12584
|
* @returns This entity for chaining
|
|
12496
12585
|
*/
|
|
12497
12586
|
wakeUp() {
|
|
12498
|
-
this.state &= ~EntityState.Sleeping;
|
|
12587
|
+
this.state &= ~EntityState$1.Sleeping;
|
|
12499
12588
|
this.timeSinceMovement = 0;
|
|
12500
12589
|
return this;
|
|
12501
12590
|
}
|
|
@@ -12510,7 +12599,7 @@ class Entity {
|
|
|
12510
12599
|
* @returns True if static
|
|
12511
12600
|
*/
|
|
12512
12601
|
isStatic() {
|
|
12513
|
-
return (this.state & EntityState.Static) !== 0 || this.invMass === 0;
|
|
12602
|
+
return (this.state & EntityState$1.Static) !== 0 || this.invMass === 0;
|
|
12514
12603
|
}
|
|
12515
12604
|
/**
|
|
12516
12605
|
* Checks if the entity is dynamic
|
|
@@ -12518,7 +12607,7 @@ class Entity {
|
|
|
12518
12607
|
* @returns True if dynamic
|
|
12519
12608
|
*/
|
|
12520
12609
|
isDynamic() {
|
|
12521
|
-
return (this.state & EntityState.Dynamic) !== 0 && this.mass > 0;
|
|
12610
|
+
return (this.state & EntityState$1.Dynamic) !== 0 && this.mass > 0;
|
|
12522
12611
|
}
|
|
12523
12612
|
/**
|
|
12524
12613
|
* Checks if the entity is sleeping
|
|
@@ -12526,7 +12615,7 @@ class Entity {
|
|
|
12526
12615
|
* @returns True if sleeping
|
|
12527
12616
|
*/
|
|
12528
12617
|
isSleeping() {
|
|
12529
|
-
return (this.state & EntityState.Sleeping) !== 0;
|
|
12618
|
+
return (this.state & EntityState$1.Sleeping) !== 0;
|
|
12530
12619
|
}
|
|
12531
12620
|
/**
|
|
12532
12621
|
* Checks if the entity is kinematic
|
|
@@ -12534,7 +12623,7 @@ class Entity {
|
|
|
12534
12623
|
* @returns True if kinematic
|
|
12535
12624
|
*/
|
|
12536
12625
|
isKinematic() {
|
|
12537
|
-
return (this.state & EntityState.Kinematic) !== 0;
|
|
12626
|
+
return (this.state & EntityState$1.Kinematic) !== 0;
|
|
12538
12627
|
}
|
|
12539
12628
|
/**
|
|
12540
12629
|
* Resets accumulated forces and torques
|
|
@@ -12739,7 +12828,7 @@ class Integrator {
|
|
|
12739
12828
|
*/
|
|
12740
12829
|
constructor(config) {
|
|
12741
12830
|
this.config = config;
|
|
12742
|
-
this.gravity = config.gravity?.clone() ?? new Vector2(0, 0);
|
|
12831
|
+
this.gravity = config.gravity?.clone() ?? new Vector2$1(0, 0);
|
|
12743
12832
|
}
|
|
12744
12833
|
/**
|
|
12745
12834
|
* Integrates an entity's motion
|
|
@@ -12949,10 +13038,10 @@ class AABBCollider {
|
|
|
12949
13038
|
let depth;
|
|
12950
13039
|
if (overlapX < overlapY) {
|
|
12951
13040
|
depth = overlapX;
|
|
12952
|
-
normal = aabbA.getCenterX() < aabbB.getCenterX() ? new Vector2(1, 0) : new Vector2(-1, 0);
|
|
13041
|
+
normal = aabbA.getCenterX() < aabbB.getCenterX() ? new Vector2$1(1, 0) : new Vector2$1(-1, 0);
|
|
12953
13042
|
} else {
|
|
12954
13043
|
depth = overlapY;
|
|
12955
|
-
normal = aabbA.getCenterY() < aabbB.getCenterY() ? new Vector2(0, 1) : new Vector2(0, -1);
|
|
13044
|
+
normal = aabbA.getCenterY() < aabbB.getCenterY() ? new Vector2$1(0, 1) : new Vector2$1(0, -1);
|
|
12956
13045
|
}
|
|
12957
13046
|
const contactPoint = intersection.getCenter();
|
|
12958
13047
|
return {
|
|
@@ -13006,7 +13095,7 @@ class AABBCollider {
|
|
|
13006
13095
|
const t = tNear < 0 ? tFar : tNear;
|
|
13007
13096
|
if (t < 0) return null;
|
|
13008
13097
|
const point = ray.getPoint(t);
|
|
13009
|
-
let normal = new Vector2(0, 0);
|
|
13098
|
+
let normal = new Vector2$1(0, 0);
|
|
13010
13099
|
if (Math.abs(point.x - bounds.minX) < 1e-5) normal.set(-1, 0);
|
|
13011
13100
|
else if (Math.abs(point.x - bounds.maxX) < 1e-5) normal.set(1, 0);
|
|
13012
13101
|
else if (Math.abs(point.y - bounds.minY) < 1e-5) normal.set(0, -1);
|
|
@@ -13088,7 +13177,7 @@ class CircleCollider {
|
|
|
13088
13177
|
const depth = minDistance - distance;
|
|
13089
13178
|
let normal;
|
|
13090
13179
|
if (distance < 1e-5) {
|
|
13091
|
-
normal = new Vector2(1, 0);
|
|
13180
|
+
normal = new Vector2$1(1, 0);
|
|
13092
13181
|
} else {
|
|
13093
13182
|
normal = centerB.sub(centerA).normalize();
|
|
13094
13183
|
}
|
|
@@ -13133,18 +13222,18 @@ class CircleCollider {
|
|
|
13133
13222
|
const distToTop = aabb.maxY - circleCenter.y;
|
|
13134
13223
|
const minDist = Math.min(distToLeft, distToRight, distToBottom, distToTop);
|
|
13135
13224
|
if (minDist === distToLeft) {
|
|
13136
|
-
normal = new Vector2(-1, 0);
|
|
13225
|
+
normal = new Vector2$1(-1, 0);
|
|
13137
13226
|
} else if (minDist === distToRight) {
|
|
13138
|
-
normal = new Vector2(1, 0);
|
|
13227
|
+
normal = new Vector2$1(1, 0);
|
|
13139
13228
|
} else if (minDist === distToBottom) {
|
|
13140
|
-
normal = new Vector2(0, -1);
|
|
13229
|
+
normal = new Vector2$1(0, -1);
|
|
13141
13230
|
} else {
|
|
13142
|
-
normal = new Vector2(0, 1);
|
|
13231
|
+
normal = new Vector2$1(0, 1);
|
|
13143
13232
|
}
|
|
13144
13233
|
} else {
|
|
13145
|
-
normal = new Vector2(closestX - circleCenter.x, closestY - circleCenter.y).normalize();
|
|
13234
|
+
normal = new Vector2$1(closestX - circleCenter.x, closestY - circleCenter.y).normalize();
|
|
13146
13235
|
}
|
|
13147
|
-
const contactPoint = new Vector2(closestX, closestY);
|
|
13236
|
+
const contactPoint = new Vector2$1(closestX, closestY);
|
|
13148
13237
|
return {
|
|
13149
13238
|
entityA: this.entity,
|
|
13150
13239
|
entityB: other.getEntity(),
|
|
@@ -13233,7 +13322,7 @@ class CapsuleCollider {
|
|
|
13233
13322
|
const t = tNear < 0 ? tFar : tNear;
|
|
13234
13323
|
if (t < 0) return null;
|
|
13235
13324
|
const point = ray.getPoint(t);
|
|
13236
|
-
let normal = new Vector2(0, 0);
|
|
13325
|
+
let normal = new Vector2$1(0, 0);
|
|
13237
13326
|
if (Math.abs(point.x - bounds.minX) < 1e-5) normal.set(-1, 0);
|
|
13238
13327
|
else if (Math.abs(point.x - bounds.maxX) < 1e-5) normal.set(1, 0);
|
|
13239
13328
|
else if (Math.abs(point.y - bounds.minY) < 1e-5) normal.set(0, -1);
|
|
@@ -13270,8 +13359,8 @@ class CapsuleCollider {
|
|
|
13270
13359
|
const pos = this.entity.position;
|
|
13271
13360
|
const halfSegment = Math.max(0, height / 2 - radius);
|
|
13272
13361
|
return {
|
|
13273
|
-
a: new Vector2(pos.x, pos.y - halfSegment),
|
|
13274
|
-
b: new Vector2(pos.x, pos.y + halfSegment)
|
|
13362
|
+
a: new Vector2$1(pos.x, pos.y - halfSegment),
|
|
13363
|
+
b: new Vector2$1(pos.x, pos.y + halfSegment)
|
|
13275
13364
|
};
|
|
13276
13365
|
}
|
|
13277
13366
|
testCircle(circle) {
|
|
@@ -13286,7 +13375,7 @@ class CapsuleCollider {
|
|
|
13286
13375
|
return null;
|
|
13287
13376
|
}
|
|
13288
13377
|
const dist = Math.sqrt(distSq);
|
|
13289
|
-
const normal = dist > 0 ? circleCenter.sub(closest).normalize() : new Vector2(1, 0);
|
|
13378
|
+
const normal = dist > 0 ? circleCenter.sub(closest).normalize() : new Vector2$1(1, 0);
|
|
13290
13379
|
const depth = minDist - dist;
|
|
13291
13380
|
return {
|
|
13292
13381
|
entityA: this.entity,
|
|
@@ -13318,7 +13407,7 @@ class CapsuleCollider {
|
|
|
13318
13407
|
return null;
|
|
13319
13408
|
}
|
|
13320
13409
|
const dist = Math.sqrt(distSq);
|
|
13321
|
-
const normal = dist > 0 ? closestOnBox.sub(closestOnSeg).normalize() : new Vector2(0, 1);
|
|
13410
|
+
const normal = dist > 0 ? closestOnBox.sub(closestOnSeg).normalize() : new Vector2$1(0, 1);
|
|
13322
13411
|
const depth = capRadius - dist;
|
|
13323
13412
|
return {
|
|
13324
13413
|
entityA: this.entity,
|
|
@@ -13344,7 +13433,7 @@ class CapsuleCollider {
|
|
|
13344
13433
|
return null;
|
|
13345
13434
|
}
|
|
13346
13435
|
const dist = Math.sqrt(distSq);
|
|
13347
|
-
const normal = dist > 0 ? p2.sub(p1).normalize() : new Vector2(1, 0);
|
|
13436
|
+
const normal = dist > 0 ? p2.sub(p1).normalize() : new Vector2$1(1, 0);
|
|
13348
13437
|
const depth = minDist - dist;
|
|
13349
13438
|
return {
|
|
13350
13439
|
entityA: this.entity,
|
|
@@ -13488,12 +13577,12 @@ class PolygonCollider {
|
|
|
13488
13577
|
const b = other.getBounds();
|
|
13489
13578
|
const halfW = (b.maxX - b.minX) / 2;
|
|
13490
13579
|
const halfH = (b.maxY - b.minY) / 2;
|
|
13491
|
-
const center = new Vector2((b.minX + b.maxX) / 2, (b.minY + b.maxY) / 2);
|
|
13580
|
+
const center = new Vector2$1((b.minX + b.maxX) / 2, (b.minY + b.maxY) / 2);
|
|
13492
13581
|
const aabbPolyLocal = [
|
|
13493
|
-
new Vector2(-halfW, -halfH),
|
|
13494
|
-
new Vector2(halfW, -halfH),
|
|
13495
|
-
new Vector2(halfW, halfH),
|
|
13496
|
-
new Vector2(-halfW, halfH)
|
|
13582
|
+
new Vector2$1(-halfW, -halfH),
|
|
13583
|
+
new Vector2$1(halfW, -halfH),
|
|
13584
|
+
new Vector2$1(halfW, halfH),
|
|
13585
|
+
new Vector2$1(-halfW, halfH)
|
|
13497
13586
|
];
|
|
13498
13587
|
const tempEntity = new Entity({ position: center, rotation: 0, mass: 0 });
|
|
13499
13588
|
entityToPolygonConfig.set(tempEntity, { vertices: aabbPolyLocal, isConvex: true });
|
|
@@ -13529,7 +13618,7 @@ class PolygonCollider {
|
|
|
13529
13618
|
if (!closestPoint) continue;
|
|
13530
13619
|
const dist = Math.sqrt(minDistSq);
|
|
13531
13620
|
if (dist <= r) {
|
|
13532
|
-
const normal = dist > 1e-6 ? center.sub(closestPoint).normalize() : new Vector2(1, 0);
|
|
13621
|
+
const normal = dist > 1e-6 ? center.sub(closestPoint).normalize() : new Vector2$1(1, 0);
|
|
13533
13622
|
const depth = r - dist;
|
|
13534
13623
|
const info = {
|
|
13535
13624
|
entityA: this.entity,
|
|
@@ -13637,12 +13726,12 @@ class PolygonCollider {
|
|
|
13637
13726
|
const t = ((v1.x - v3.x) * (v3.y - v4.y) - (v1.y - v3.y) * (v3.x - v4.x)) / den;
|
|
13638
13727
|
const u = -((v1.x - v2.x) * (v1.y - v3.y) - (v1.y - v2.y) * (v1.x - v3.x)) / den;
|
|
13639
13728
|
if (t >= 0 && t <= ray.length && u >= 0 && u <= 1) {
|
|
13640
|
-
const point = new Vector2(
|
|
13729
|
+
const point = new Vector2$1(
|
|
13641
13730
|
v1.x + t * (v2.x - v1.x),
|
|
13642
13731
|
v1.y + t * (v2.y - v1.y)
|
|
13643
13732
|
);
|
|
13644
13733
|
const segmentDir = p2.sub(p1).normalize();
|
|
13645
|
-
let normal = new Vector2(-segmentDir.y, segmentDir.x);
|
|
13734
|
+
let normal = new Vector2$1(-segmentDir.y, segmentDir.x);
|
|
13646
13735
|
if (normal.dot(ray.direction) > 0) {
|
|
13647
13736
|
normal = normal.mul(-1);
|
|
13648
13737
|
}
|
|
@@ -13667,7 +13756,7 @@ class PolygonCollider {
|
|
|
13667
13756
|
for (let i = 0; i < part.length; i++) {
|
|
13668
13757
|
const v = part[i];
|
|
13669
13758
|
if (!v) continue;
|
|
13670
|
-
w[i] = new Vector2(v.x * cos - v.y * sin + px, v.x * sin + v.y * cos + py);
|
|
13759
|
+
w[i] = new Vector2$1(v.x * cos - v.y * sin + px, v.x * sin + v.y * cos + py);
|
|
13671
13760
|
}
|
|
13672
13761
|
worldParts.push(w);
|
|
13673
13762
|
}
|
|
@@ -13687,7 +13776,7 @@ function gatherSATAxes(a, b) {
|
|
|
13687
13776
|
const p1 = p[(i + 1) % p.length];
|
|
13688
13777
|
if (!p0 || !p1) return;
|
|
13689
13778
|
const edge = p1.sub(p0);
|
|
13690
|
-
const axis = new Vector2(-edge.y, edge.x).normalize();
|
|
13779
|
+
const axis = new Vector2$1(-edge.y, edge.x).normalize();
|
|
13691
13780
|
axes.push(axis);
|
|
13692
13781
|
};
|
|
13693
13782
|
for (let i = 0; i < a.length; i++) pushAxis(a, i);
|
|
@@ -13715,7 +13804,7 @@ function polygonCentroid(poly) {
|
|
|
13715
13804
|
cy += v.y;
|
|
13716
13805
|
}
|
|
13717
13806
|
const n = poly.length > 0 ? poly.length : 1;
|
|
13718
|
-
return new Vector2(cx / n, cy / n);
|
|
13807
|
+
return new Vector2$1(cx / n, cy / n);
|
|
13719
13808
|
}
|
|
13720
13809
|
|
|
13721
13810
|
const colliderCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -14132,7 +14221,7 @@ class Ray {
|
|
|
14132
14221
|
}
|
|
14133
14222
|
|
|
14134
14223
|
function raycast(partition, origin, direction, maxDistance, mask, filter) {
|
|
14135
|
-
const dir = direction.length() > 0 ? direction.normalize() : new Vector2(1, 0);
|
|
14224
|
+
const dir = direction.length() > 0 ? direction.normalize() : new Vector2$1(1, 0);
|
|
14136
14225
|
const end = origin.add(dir.mul(maxDistance));
|
|
14137
14226
|
const candidates = partition.raycast(new Ray(origin, dir, maxDistance), mask, filter);
|
|
14138
14227
|
if (candidates) return candidates;
|
|
@@ -14196,8 +14285,8 @@ function raycastAABB(box, origin, dir, maxDistance) {
|
|
|
14196
14285
|
if (tmax < tmin || tmin < 0 || tmin > maxDistance) return null;
|
|
14197
14286
|
const point = origin.add(dir.mul(tmin));
|
|
14198
14287
|
let normal;
|
|
14199
|
-
if (tmin === tminX) normal = new Vector2(dir.x > 0 ? -1 : 1, 0);
|
|
14200
|
-
else normal = new Vector2(0, dir.y > 0 ? -1 : 1);
|
|
14288
|
+
if (tmin === tminX) normal = new Vector2$1(dir.x > 0 ? -1 : 1, 0);
|
|
14289
|
+
else normal = new Vector2$1(0, dir.y > 0 ? -1 : 1);
|
|
14201
14290
|
return { entity: box.getEntity(), point, normal, distance: tmin };
|
|
14202
14291
|
}
|
|
14203
14292
|
function raycastPolygon(poly, origin, dir, maxDistance) {
|
|
@@ -14219,7 +14308,7 @@ function raycastPolygon(poly, origin, dir, maxDistance) {
|
|
|
14219
14308
|
bestT = t;
|
|
14220
14309
|
bestPoint = hit.point;
|
|
14221
14310
|
const edge = b.sub(a);
|
|
14222
|
-
const n = new Vector2(-edge.y, edge.x).normalize();
|
|
14311
|
+
const n = new Vector2$1(-edge.y, edge.x).normalize();
|
|
14223
14312
|
bestNormal = n;
|
|
14224
14313
|
}
|
|
14225
14314
|
}
|
|
@@ -14230,13 +14319,13 @@ function raycastPolygon(poly, origin, dir, maxDistance) {
|
|
|
14230
14319
|
function segmentRayIntersection(a, b, r0, r1) {
|
|
14231
14320
|
const v1 = r0.sub(a);
|
|
14232
14321
|
const v2 = b.sub(a);
|
|
14233
|
-
const v3 = new Vector2(-(r1.y - r0.y), r1.x - r0.x);
|
|
14322
|
+
const v3 = new Vector2$1(-(r1.y - r0.y), r1.x - r0.x);
|
|
14234
14323
|
const denom = v2.dot(v3);
|
|
14235
14324
|
if (Math.abs(denom) < 1e-9) return null;
|
|
14236
14325
|
const t1 = v2.cross(v1) / denom;
|
|
14237
14326
|
const t2 = v1.dot(v3) / denom;
|
|
14238
14327
|
if (t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1) {
|
|
14239
|
-
const hitPoint = new Vector2(r0.x + (r1.x - r0.x) * t1, r0.y + (r1.y - r0.y) * t1);
|
|
14328
|
+
const hitPoint = new Vector2$1(r0.x + (r1.x - r0.x) * t1, r0.y + (r1.y - r0.y) * t1);
|
|
14240
14329
|
const dist = hitPoint.sub(r0).length();
|
|
14241
14330
|
return { point: hitPoint, distance: dist };
|
|
14242
14331
|
}
|
|
@@ -14274,6 +14363,11 @@ class CollisionResolver {
|
|
|
14274
14363
|
/**
|
|
14275
14364
|
* Separates two entities by moving them apart
|
|
14276
14365
|
*
|
|
14366
|
+
* This method applies position corrections to resolve penetration between
|
|
14367
|
+
* colliding entities. After applying corrections, it notifies position change
|
|
14368
|
+
* handlers to ensure proper synchronization with game logic (e.g., updating
|
|
14369
|
+
* owner.x/y signals for network sync).
|
|
14370
|
+
*
|
|
14277
14371
|
* @param entityA - First entity
|
|
14278
14372
|
* @param entityB - Second entity
|
|
14279
14373
|
* @param normal - Separation normal (from A to B)
|
|
@@ -14292,9 +14386,11 @@ class CollisionResolver {
|
|
|
14292
14386
|
const correctionB = normal.mul(correction * (entityB.invMass / totalInvMass));
|
|
14293
14387
|
if (!entityA.isStatic()) {
|
|
14294
14388
|
entityA.position.addInPlace(correctionA);
|
|
14389
|
+
entityA.notifyPositionChange();
|
|
14295
14390
|
}
|
|
14296
14391
|
if (!entityB.isStatic()) {
|
|
14297
14392
|
entityB.position.addInPlace(correctionB);
|
|
14393
|
+
entityB.notifyPositionChange();
|
|
14298
14394
|
}
|
|
14299
14395
|
}
|
|
14300
14396
|
/**
|
|
@@ -14413,7 +14509,7 @@ function sweepCircleAABB(circle, box, delta) {
|
|
|
14413
14509
|
const p0 = circle.getCenter();
|
|
14414
14510
|
const dir = delta;
|
|
14415
14511
|
const maxDist = 1;
|
|
14416
|
-
const origin = new Vector2(0, 0);
|
|
14512
|
+
const origin = new Vector2$1(0, 0);
|
|
14417
14513
|
const bb = new AABB(expanded.minX - p0.x, expanded.minY - p0.y, expanded.maxX - p0.x, expanded.maxY - p0.y);
|
|
14418
14514
|
const res = rayVsAABB(origin, dir, bb, maxDist);
|
|
14419
14515
|
if (!res) return null;
|
|
@@ -14436,11 +14532,11 @@ function sweepAABBAABB(a, b, delta) {
|
|
|
14436
14532
|
if (tEntry > tExit || tEntry < 0 || tEntry > 1) return null;
|
|
14437
14533
|
let normal;
|
|
14438
14534
|
if (Math.min(xEntry, xExit) > Math.min(yEntry, yExit)) {
|
|
14439
|
-
normal = new Vector2(delta.x > 0 ? -1 : 1, 0);
|
|
14535
|
+
normal = new Vector2$1(delta.x > 0 ? -1 : 1, 0);
|
|
14440
14536
|
} else {
|
|
14441
|
-
normal = new Vector2(0, delta.y > 0 ? -1 : 1);
|
|
14537
|
+
normal = new Vector2$1(0, delta.y > 0 ? -1 : 1);
|
|
14442
14538
|
}
|
|
14443
|
-
const hitPoint = new Vector2(
|
|
14539
|
+
const hitPoint = new Vector2$1(
|
|
14444
14540
|
delta.x !== 0 ? delta.x > 0 ? A.maxX : A.minX : (A.minX + A.maxX) * 0.5,
|
|
14445
14541
|
delta.y !== 0 ? delta.y > 0 ? A.maxY : A.minY : (A.minY + A.maxY) * 0.5
|
|
14446
14542
|
);
|
|
@@ -14462,7 +14558,7 @@ function rayVsAABB(origin, dir, b, maxT) {
|
|
|
14462
14558
|
tmin = Math.max(tmin, Math.max(tminX, tminY));
|
|
14463
14559
|
tmax = Math.min(tmax, Math.min(tmaxX, tmaxY));
|
|
14464
14560
|
if (tmax < tmin || tmin < 0 || tmin > maxT) return null;
|
|
14465
|
-
const normal = tmin === tminX ? new Vector2(dir.x > 0 ? -1 : 1, 0) : new Vector2(0, dir.y > 0 ? -1 : 1);
|
|
14561
|
+
const normal = tmin === tminX ? new Vector2$1(dir.x > 0 ? -1 : 1, 0) : new Vector2$1(0, dir.y > 0 ? -1 : 1);
|
|
14466
14562
|
return { t: tmin, normal };
|
|
14467
14563
|
}
|
|
14468
14564
|
|
|
@@ -15367,7 +15463,7 @@ class EntityMovementBody {
|
|
|
15367
15463
|
this.entity.setVelocity(velocity);
|
|
15368
15464
|
}
|
|
15369
15465
|
translate(delta) {
|
|
15370
|
-
this.entity.position.addInPlace(new Vector2(delta.x, delta.y));
|
|
15466
|
+
this.entity.position.addInPlace(new Vector2$1(delta.x, delta.y));
|
|
15371
15467
|
}
|
|
15372
15468
|
isStatic() {
|
|
15373
15469
|
return this.entity.isStatic();
|
|
@@ -15624,19 +15720,19 @@ class ZoneManager {
|
|
|
15624
15720
|
attachedEntity = config.entity;
|
|
15625
15721
|
const entityPos = attachedEntity.position;
|
|
15626
15722
|
const offsetValue = config.offset ?? { x: 0, y: 0 };
|
|
15627
|
-
if (offsetValue instanceof Vector2) {
|
|
15723
|
+
if (offsetValue instanceof Vector2$1) {
|
|
15628
15724
|
offset = offsetValue.clone();
|
|
15629
15725
|
} else {
|
|
15630
|
-
offset = new Vector2(offsetValue.x, offsetValue.y);
|
|
15726
|
+
offset = new Vector2$1(offsetValue.x, offsetValue.y);
|
|
15631
15727
|
}
|
|
15632
|
-
position = new Vector2(entityPos.x + offset.x, entityPos.y + offset.y);
|
|
15728
|
+
position = new Vector2$1(entityPos.x + offset.x, entityPos.y + offset.y);
|
|
15633
15729
|
} else {
|
|
15634
15730
|
type = "static";
|
|
15635
15731
|
const pos = config.position;
|
|
15636
|
-
if (pos instanceof Vector2) {
|
|
15732
|
+
if (pos instanceof Vector2$1) {
|
|
15637
15733
|
position = pos.clone();
|
|
15638
15734
|
} else {
|
|
15639
|
-
position = new Vector2(pos.x, pos.y);
|
|
15735
|
+
position = new Vector2$1(pos.x, pos.y);
|
|
15640
15736
|
}
|
|
15641
15737
|
}
|
|
15642
15738
|
const record = {
|
|
@@ -15714,10 +15810,10 @@ class ZoneManager {
|
|
|
15714
15810
|
}
|
|
15715
15811
|
if ("offset" in updates && updates.offset !== void 0 && zone.type === "attached") {
|
|
15716
15812
|
const offsetValue = updates.offset;
|
|
15717
|
-
if (offsetValue instanceof Vector2) {
|
|
15813
|
+
if (offsetValue instanceof Vector2$1) {
|
|
15718
15814
|
zone.offset = offsetValue.clone();
|
|
15719
15815
|
} else {
|
|
15720
|
-
zone.offset = new Vector2(offsetValue.x, offsetValue.y);
|
|
15816
|
+
zone.offset = new Vector2$1(offsetValue.x, offsetValue.y);
|
|
15721
15817
|
}
|
|
15722
15818
|
}
|
|
15723
15819
|
return true;
|
|
@@ -15821,7 +15917,7 @@ class ZoneManager {
|
|
|
15821
15917
|
for (const zone of this.zones.values()) {
|
|
15822
15918
|
if (zone.type === "attached" && zone.attachedEntity) {
|
|
15823
15919
|
const entityPos = zone.attachedEntity.position;
|
|
15824
|
-
const offset = zone.offset ?? new Vector2(0, 0);
|
|
15920
|
+
const offset = zone.offset ?? new Vector2$1(0, 0);
|
|
15825
15921
|
zone.position.set(entityPos.x + offset.x, entityPos.y + offset.y);
|
|
15826
15922
|
}
|
|
15827
15923
|
const aabb = new AABB(
|
|
@@ -16620,7 +16716,7 @@ class LinearRepulsion {
|
|
|
16620
16716
|
throw new Error("LinearRepulsion requires a movement body backed by a physics entity.");
|
|
16621
16717
|
}
|
|
16622
16718
|
const targetPosition = this.targetProvider();
|
|
16623
|
-
const toTarget = new Vector2(targetPosition.x - entity.position.x, targetPosition.y - entity.position.y);
|
|
16719
|
+
const toTarget = new Vector2$1(targetPosition.x - entity.position.x, targetPosition.y - entity.position.y);
|
|
16624
16720
|
const distance = toTarget.length();
|
|
16625
16721
|
if (distance > 0) {
|
|
16626
16722
|
toTarget.divInPlace(distance);
|
|
@@ -16630,12 +16726,12 @@ class LinearRepulsion {
|
|
|
16630
16726
|
const bounds = AABB.fromCenterSize(entity.position.x, entity.position.y, this.repulseRadius * 2, this.repulseRadius * 2);
|
|
16631
16727
|
const neighbors = this.engine.queryAABB(bounds);
|
|
16632
16728
|
const ignored = this.ignoredEntity?.();
|
|
16633
|
-
const push = new Vector2(0, 0);
|
|
16729
|
+
const push = new Vector2$1(0, 0);
|
|
16634
16730
|
for (const other of neighbors) {
|
|
16635
16731
|
if (other === entity || other === ignored || other.isStatic()) {
|
|
16636
16732
|
continue;
|
|
16637
16733
|
}
|
|
16638
|
-
const diff = new Vector2(entity.position.x - other.position.x, entity.position.y - other.position.y);
|
|
16734
|
+
const diff = new Vector2$1(entity.position.x - other.position.x, entity.position.y - other.position.y);
|
|
16639
16735
|
const d2 = diff.lengthSquared();
|
|
16640
16736
|
if (d2 > this.repulseRadiusSq || d2 === 0) {
|
|
16641
16737
|
continue;
|
|
@@ -16876,7 +16972,7 @@ class ProjectileMovement {
|
|
|
16876
16972
|
return;
|
|
16877
16973
|
}
|
|
16878
16974
|
if (this.startPosition === null) {
|
|
16879
|
-
this.startPosition = new Vector2(body.position.x, body.position.y);
|
|
16975
|
+
this.startPosition = new Vector2$1(body.position.x, body.position.y);
|
|
16880
16976
|
}
|
|
16881
16977
|
this.elapsed += dt;
|
|
16882
16978
|
if (this.options.lifetime !== void 0 && this.elapsed >= this.options.lifetime) {
|
|
@@ -16895,7 +16991,7 @@ class ProjectileMovement {
|
|
|
16895
16991
|
return;
|
|
16896
16992
|
}
|
|
16897
16993
|
if (this.startPosition) {
|
|
16898
|
-
this.distanceTraveled = new Vector2(body.position.x, body.position.y).distanceTo(this.startPosition);
|
|
16994
|
+
this.distanceTraveled = new Vector2$1(body.position.x, body.position.y).distanceTo(this.startPosition);
|
|
16899
16995
|
if (this.options.maxRange !== void 0 && this.distanceTraveled >= this.options.maxRange) {
|
|
16900
16996
|
this.finish(body);
|
|
16901
16997
|
}
|
|
@@ -17008,7 +17104,7 @@ class SeekAvoid {
|
|
|
17008
17104
|
body.setVelocity({ x: 0, y: 0 });
|
|
17009
17105
|
return;
|
|
17010
17106
|
}
|
|
17011
|
-
const toTarget = new Vector2(target.position.x - entity.position.x, target.position.y - entity.position.y);
|
|
17107
|
+
const toTarget = new Vector2$1(target.position.x - entity.position.x, target.position.y - entity.position.y);
|
|
17012
17108
|
const distSq = toTarget.lengthSquared();
|
|
17013
17109
|
let arrived = false;
|
|
17014
17110
|
if (distSq <= this.arriveRadiusSq) {
|
|
@@ -17019,13 +17115,13 @@ class SeekAvoid {
|
|
|
17019
17115
|
}
|
|
17020
17116
|
const bounds = AABB.fromCenterSize(entity.position.x, entity.position.y, this.repulseRadius * 2, this.repulseRadius * 2);
|
|
17021
17117
|
const neighbors = this.engine.queryAABB(bounds);
|
|
17022
|
-
const push = new Vector2(0, 0);
|
|
17118
|
+
const push = new Vector2$1(0, 0);
|
|
17023
17119
|
if (!arrived) {
|
|
17024
17120
|
for (const other of neighbors) {
|
|
17025
17121
|
if (other === entity || other === target || other.isStatic()) {
|
|
17026
17122
|
continue;
|
|
17027
17123
|
}
|
|
17028
|
-
const diff = new Vector2(entity.position.x - other.position.x, entity.position.y - other.position.y);
|
|
17124
|
+
const diff = new Vector2$1(entity.position.x - other.position.x, entity.position.y - other.position.y);
|
|
17029
17125
|
let d2 = diff.lengthSquared();
|
|
17030
17126
|
if (d2 > this.repulseRadiusSq) {
|
|
17031
17127
|
continue;
|
|
@@ -17109,7 +17205,7 @@ class RpgCommonMap {
|
|
|
17109
17205
|
this.data = signal(null);
|
|
17110
17206
|
this.physic = new PhysicsEngine({
|
|
17111
17207
|
timeStep: 1 / 60,
|
|
17112
|
-
gravity: new Vector2(0, 0),
|
|
17208
|
+
gravity: new Vector2$1(0, 0),
|
|
17113
17209
|
enableSleep: false
|
|
17114
17210
|
});
|
|
17115
17211
|
this.moveManager = new MovementManager(() => this.physic);
|
|
@@ -17123,12 +17219,33 @@ class RpgCommonMap {
|
|
|
17123
17219
|
* It's shared using the share() operator, meaning that all subscribers will receive
|
|
17124
17220
|
* events from a single interval rather than creating multiple intervals.
|
|
17125
17221
|
*
|
|
17222
|
+
* ## Physics Loop Architecture
|
|
17223
|
+
*
|
|
17224
|
+
* The physics simulation is centralized in this game loop:
|
|
17225
|
+
*
|
|
17226
|
+
* 1. **Input Processing** (`processInput`): Only updates entity velocities, does NOT step physics
|
|
17227
|
+
* 2. **Game Loop** (`tick$` -> `runFixedTicks`): Executes physics simulation with fixed timestep
|
|
17228
|
+
* 3. **Fixed Timestep Pattern**: Accumulator-based approach ensures deterministic physics
|
|
17229
|
+
*
|
|
17230
|
+
* ```
|
|
17231
|
+
* Input Events ─────────────────────────────────────────────────────────────►
|
|
17232
|
+
* │
|
|
17233
|
+
* ▼ (update velocity only)
|
|
17234
|
+
* ┌─────────────────────────────────────────────────────────────────────────┐
|
|
17235
|
+
* │ Game Loop (tick$) │
|
|
17236
|
+
* │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
|
17237
|
+
* │ │ updateMovements │ → │ stepOneTick │ → │ postTickUpdates │ │
|
|
17238
|
+
* │ │ (apply velocity)│ │ (physics step) │ │ (zones, sync) │ │
|
|
17239
|
+
* │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
|
|
17240
|
+
* └─────────────────────────────────────────────────────────────────────────┘
|
|
17241
|
+
* ```
|
|
17242
|
+
*
|
|
17126
17243
|
* @example
|
|
17127
17244
|
* ```ts
|
|
17128
|
-
* // Subscribe to the game tick
|
|
17129
|
-
* map.tick$.subscribe(timestamp => {
|
|
17130
|
-
* //
|
|
17131
|
-
* this.
|
|
17245
|
+
* // Subscribe to the game tick for custom updates
|
|
17246
|
+
* map.tick$.subscribe(({ delta, timestamp }) => {
|
|
17247
|
+
* // Custom game logic runs alongside physics
|
|
17248
|
+
* this.updateCustomEntities(delta);
|
|
17132
17249
|
* });
|
|
17133
17250
|
* ```
|
|
17134
17251
|
*/
|
|
@@ -17304,6 +17421,43 @@ class RpgCommonMap {
|
|
|
17304
17421
|
getObjectById(id) {
|
|
17305
17422
|
return this.players()[id] ?? this.events()[id];
|
|
17306
17423
|
}
|
|
17424
|
+
/**
|
|
17425
|
+
* Execute physics simulation with fixed timestep
|
|
17426
|
+
*
|
|
17427
|
+
* This method runs the physics engine using a fixed timestep accumulator pattern.
|
|
17428
|
+
* It ensures deterministic physics regardless of frame rate by:
|
|
17429
|
+
* 1. Accumulating delta time
|
|
17430
|
+
* 2. Running fixed-size physics steps until the accumulator is depleted
|
|
17431
|
+
* 3. Calling `updateMovements()` before each step to apply velocity changes
|
|
17432
|
+
* 4. Running post-tick updates (zones, callbacks) after each step
|
|
17433
|
+
*
|
|
17434
|
+
* ## Architecture
|
|
17435
|
+
*
|
|
17436
|
+
* The physics loop is centralized here and called from `tick$` subscription.
|
|
17437
|
+
* Input processing (`processInput`) only updates entity velocities - it does NOT
|
|
17438
|
+
* step the physics. This ensures:
|
|
17439
|
+
* - Consistent physics timing (60fps fixed timestep)
|
|
17440
|
+
* - No double-stepping when inputs are processed
|
|
17441
|
+
* - Proper accumulator-based interpolation support
|
|
17442
|
+
*
|
|
17443
|
+
* @param deltaMs - Time elapsed since last call in milliseconds
|
|
17444
|
+
* @param hooks - Optional callbacks for before/after each physics step
|
|
17445
|
+
* @returns Number of physics ticks executed
|
|
17446
|
+
*
|
|
17447
|
+
* @example
|
|
17448
|
+
* ```ts
|
|
17449
|
+
* // Called automatically by tick$ subscription
|
|
17450
|
+
* this.tickSubscription = this.tick$.subscribe(({ delta }) => {
|
|
17451
|
+
* this.runFixedTicks(delta);
|
|
17452
|
+
* });
|
|
17453
|
+
*
|
|
17454
|
+
* // Or manually with hooks for debugging
|
|
17455
|
+
* this.runFixedTicks(16, {
|
|
17456
|
+
* beforeStep: () => console.log('Before physics step'),
|
|
17457
|
+
* afterStep: (tick) => console.log(`Physics tick ${tick} completed`)
|
|
17458
|
+
* });
|
|
17459
|
+
* ```
|
|
17460
|
+
*/
|
|
17307
17461
|
runFixedTicks(deltaMs, hooks) {
|
|
17308
17462
|
if (!Number.isFinite(deltaMs) || deltaMs <= 0) {
|
|
17309
17463
|
return 0;
|
|
@@ -17314,12 +17468,46 @@ class RpgCommonMap {
|
|
|
17314
17468
|
while (this.physicsAccumulatorMs >= fixedStepMs) {
|
|
17315
17469
|
this.physicsAccumulatorMs -= fixedStepMs;
|
|
17316
17470
|
hooks?.beforeStep?.();
|
|
17471
|
+
this.physic.updateMovements();
|
|
17317
17472
|
const tick = this.physic.stepOneTick();
|
|
17318
17473
|
executed += 1;
|
|
17474
|
+
this.runPostTickUpdates();
|
|
17319
17475
|
hooks?.afterStep?.(tick);
|
|
17320
17476
|
}
|
|
17321
17477
|
return executed;
|
|
17322
17478
|
}
|
|
17479
|
+
/**
|
|
17480
|
+
* Force a single physics tick outside of the normal game loop
|
|
17481
|
+
*
|
|
17482
|
+
* This method is primarily used for **client-side prediction** where the client
|
|
17483
|
+
* needs to immediately simulate physics in response to local input, rather than
|
|
17484
|
+
* waiting for the next game loop tick.
|
|
17485
|
+
*
|
|
17486
|
+
* ## Use Cases
|
|
17487
|
+
*
|
|
17488
|
+
* - **Client-side prediction**: Immediately simulate player movement for responsive feel
|
|
17489
|
+
* - **Testing**: Force a physics step in unit tests
|
|
17490
|
+
* - **Special effects**: Immediate physics response for specific game events
|
|
17491
|
+
*
|
|
17492
|
+
* ## Important
|
|
17493
|
+
*
|
|
17494
|
+
* This method should NOT be used on the server for normal input processing.
|
|
17495
|
+
* Server-side physics is handled by `runFixedTicks` in the main game loop to ensure
|
|
17496
|
+
* deterministic simulation.
|
|
17497
|
+
*
|
|
17498
|
+
* @param hooks - Optional callbacks for before/after the physics step
|
|
17499
|
+
* @returns The physics tick number
|
|
17500
|
+
*
|
|
17501
|
+
* @example
|
|
17502
|
+
* ```ts
|
|
17503
|
+
* // Client-side: immediately simulate predicted movement
|
|
17504
|
+
* class RpgClientMap extends RpgCommonMap {
|
|
17505
|
+
* stepPredictionTick(): void {
|
|
17506
|
+
* this.forceSingleTick();
|
|
17507
|
+
* }
|
|
17508
|
+
* }
|
|
17509
|
+
* ```
|
|
17510
|
+
*/
|
|
17323
17511
|
forceSingleTick(hooks) {
|
|
17324
17512
|
hooks?.beforeStep?.();
|
|
17325
17513
|
this.physic.updateMovements();
|
|
@@ -17613,13 +17801,13 @@ class RpgCommonMap {
|
|
|
17613
17801
|
width: boxWidth,
|
|
17614
17802
|
height: boxHeight,
|
|
17615
17803
|
mass: Infinity,
|
|
17616
|
-
state: EntityState.Static,
|
|
17804
|
+
state: EntityState$1.Static,
|
|
17617
17805
|
restitution: 0
|
|
17618
17806
|
});
|
|
17619
17807
|
entity.freeze();
|
|
17620
17808
|
const localVertices = points.map((point) => {
|
|
17621
17809
|
const [px, py] = point;
|
|
17622
|
-
return new Vector2(px - centerX, py - centerY);
|
|
17810
|
+
return new Vector2$1(px - centerX, py - centerY);
|
|
17623
17811
|
});
|
|
17624
17812
|
assignPolygonCollider(entity, { vertices: localVertices });
|
|
17625
17813
|
} else {
|
|
@@ -17636,7 +17824,7 @@ class RpgCommonMap {
|
|
|
17636
17824
|
width: boxWidth,
|
|
17637
17825
|
height: boxHeight,
|
|
17638
17826
|
mass: Infinity,
|
|
17639
|
-
state: EntityState.Static,
|
|
17827
|
+
state: EntityState$1.Static,
|
|
17640
17828
|
restitution: 0
|
|
17641
17829
|
});
|
|
17642
17830
|
entity.freeze();
|
|
@@ -17647,23 +17835,60 @@ class RpgCommonMap {
|
|
|
17647
17835
|
* Add a character to the physics world
|
|
17648
17836
|
* @private
|
|
17649
17837
|
*/
|
|
17838
|
+
/**
|
|
17839
|
+
* Add a character entity to the physics world
|
|
17840
|
+
*
|
|
17841
|
+
* Creates a physics entity for a character (player or NPC) with proper position handling.
|
|
17842
|
+
* The owner's x/y signals represent **top-left** coordinates, while the physics entity
|
|
17843
|
+
* uses **center** coordinates internally.
|
|
17844
|
+
*
|
|
17845
|
+
* ## Position System
|
|
17846
|
+
*
|
|
17847
|
+
* - `owner.x()` / `owner.y()` → **top-left** corner of the character's hitbox
|
|
17848
|
+
* - `entity.position` → **center** of the physics collider
|
|
17849
|
+
* - Conversion: `center = topLeft + (size / 2)`
|
|
17850
|
+
*
|
|
17851
|
+
* @param options - Character configuration
|
|
17852
|
+
* @returns The character's unique ID
|
|
17853
|
+
*
|
|
17854
|
+
* @example
|
|
17855
|
+
* ```ts
|
|
17856
|
+
* // Player at top-left position (100, 100) with 32x32 hitbox
|
|
17857
|
+
* // Physics entity will be at center (116, 116)
|
|
17858
|
+
* this.addCharacter({
|
|
17859
|
+
* owner: player,
|
|
17860
|
+
* x: 116, // center X (ignored, uses owner.x())
|
|
17861
|
+
* y: 116, // center Y (ignored, uses owner.y())
|
|
17862
|
+
* kind: "hero"
|
|
17863
|
+
* });
|
|
17864
|
+
* ```
|
|
17865
|
+
*
|
|
17866
|
+
* @private
|
|
17867
|
+
*/
|
|
17650
17868
|
addCharacter(options) {
|
|
17651
17869
|
if (!options || typeof options.owner?.id !== "string") {
|
|
17652
17870
|
throw new Error("Character requires an owner object with a string id");
|
|
17653
17871
|
}
|
|
17654
17872
|
const owner = options.owner;
|
|
17655
17873
|
const id = owner.id;
|
|
17656
|
-
const
|
|
17657
|
-
const
|
|
17658
|
-
const
|
|
17659
|
-
const
|
|
17660
|
-
const
|
|
17661
|
-
const
|
|
17874
|
+
const hitbox = typeof owner.hitbox === "function" ? owner.hitbox() : owner.hitbox;
|
|
17875
|
+
const width = hitbox?.w ?? 32;
|
|
17876
|
+
const height = hitbox?.h ?? 32;
|
|
17877
|
+
const radius = Math.max(width, height) / 2;
|
|
17878
|
+
const topLeftX = owner.x();
|
|
17879
|
+
const topLeftY = owner.y();
|
|
17880
|
+
const centerX = topLeftX + width / 2;
|
|
17881
|
+
const centerY = topLeftY + height / 2;
|
|
17662
17882
|
const isStatic = !!options.isStatic;
|
|
17663
17883
|
const entity = this.physic.createEntity({
|
|
17664
17884
|
uuid: id,
|
|
17665
17885
|
position: { x: centerX, y: centerY },
|
|
17886
|
+
// Use radius for circular collision detection
|
|
17666
17887
|
radius: Math.max(radius, 1),
|
|
17888
|
+
// Also store explicit width/height for consistent position conversions
|
|
17889
|
+
// This ensures getBodyPosition/setBodyPosition use the same dimensions
|
|
17890
|
+
width,
|
|
17891
|
+
height,
|
|
17667
17892
|
mass: options.mass ?? (isStatic ? Infinity : 1),
|
|
17668
17893
|
friction: options.friction ?? 0.4,
|
|
17669
17894
|
linearDamping: isStatic ? 1 : 0.2,
|
|
@@ -17691,17 +17916,21 @@ class RpgCommonMap {
|
|
|
17691
17916
|
owner.animationName.set("stand");
|
|
17692
17917
|
}
|
|
17693
17918
|
});
|
|
17919
|
+
const entityWidth = width;
|
|
17920
|
+
const entityHeight = height;
|
|
17694
17921
|
entity.onPositionChange(({ x, y }) => {
|
|
17695
|
-
const
|
|
17696
|
-
const
|
|
17697
|
-
|
|
17698
|
-
const topLeftY2 = y - height / 2;
|
|
17922
|
+
const topLeftX2 = x - entityWidth / 2;
|
|
17923
|
+
const topLeftY2 = y - entityHeight / 2;
|
|
17924
|
+
let changed = false;
|
|
17699
17925
|
if (typeof owner.x === "function" && typeof owner.x.set === "function") {
|
|
17700
17926
|
owner.x.set(Math.round(topLeftX2));
|
|
17701
|
-
|
|
17927
|
+
changed = true;
|
|
17702
17928
|
}
|
|
17703
17929
|
if (typeof owner.y === "function" && typeof owner.y.set === "function") {
|
|
17704
17930
|
owner.y.set(Math.round(topLeftY2));
|
|
17931
|
+
changed = true;
|
|
17932
|
+
}
|
|
17933
|
+
if (changed) {
|
|
17705
17934
|
owner.applyFrames?.();
|
|
17706
17935
|
}
|
|
17707
17936
|
});
|
|
@@ -17917,11 +18146,11 @@ class RpgCommonMap {
|
|
|
17917
18146
|
setBodyPosition(id, x, y, mode = "center") {
|
|
17918
18147
|
const entity = this.physic.getEntityByUUID(id);
|
|
17919
18148
|
if (!entity) return;
|
|
18149
|
+
const width = entity.width || (entity.radius ? entity.radius * 2 : 32);
|
|
18150
|
+
const height = entity.height || (entity.radius ? entity.radius * 2 : 32);
|
|
17920
18151
|
let centerX = x;
|
|
17921
18152
|
let centerY = y;
|
|
17922
18153
|
if (mode === "top-left") {
|
|
17923
|
-
const width = entity.width || (entity.radius ? entity.radius * 2 : 32);
|
|
17924
|
-
const height = entity.height || (entity.radius ? entity.radius * 2 : 32);
|
|
17925
18154
|
centerX = x + width / 2;
|
|
17926
18155
|
centerY = y + height / 2;
|
|
17927
18156
|
}
|
|
@@ -18387,113 +18616,664 @@ var PrebuiltGui = /* @__PURE__ */ ((PrebuiltGui2) => {
|
|
|
18387
18616
|
return PrebuiltGui2;
|
|
18388
18617
|
})(PrebuiltGui || {});
|
|
18389
18618
|
|
|
18390
|
-
|
|
18391
|
-
|
|
18392
|
-
|
|
18393
|
-
|
|
18394
|
-
|
|
18395
|
-
|
|
18396
|
-
|
|
18397
|
-
|
|
18398
|
-
|
|
18399
|
-
|
|
18400
|
-
}
|
|
18401
|
-
|
|
18402
|
-
var __defProp$3 = Object.defineProperty;
|
|
18403
|
-
var __name = (target, value) => __defProp$3(target, "name", { value, configurable: true });
|
|
18404
|
-
|
|
18405
|
-
// src/inject.ts
|
|
18406
|
-
function provide(context, name, value) {
|
|
18407
|
-
context.set("inject:" + name, value);
|
|
18408
|
-
return value;
|
|
18409
|
-
}
|
|
18410
|
-
__name(provide, "provide");
|
|
18411
|
-
function isInjected(context, name) {
|
|
18412
|
-
return context.get("injected:" + name) === true;
|
|
18413
|
-
}
|
|
18414
|
-
__name(isInjected, "isInjected");
|
|
18415
|
-
function isProvided(context, name) {
|
|
18416
|
-
return context.get("inject:" + name) !== void 0;
|
|
18417
|
-
}
|
|
18418
|
-
__name(isProvided, "isProvided");
|
|
18419
|
-
function inject$1(context, service, args = []) {
|
|
18420
|
-
const isClass = typeof service === "function";
|
|
18421
|
-
const name = isClass ? service.name : service;
|
|
18422
|
-
const value = context.get("inject:" + name);
|
|
18423
|
-
if (value) {
|
|
18424
|
-
context.set("injected:" + name, true);
|
|
18425
|
-
return value;
|
|
18619
|
+
const _Vector2 = class _Vector2 {
|
|
18620
|
+
/**
|
|
18621
|
+
* Creates a new Vector2
|
|
18622
|
+
*
|
|
18623
|
+
* @param x - X component (default: 0)
|
|
18624
|
+
* @param y - Y component (default: 0)
|
|
18625
|
+
*/
|
|
18626
|
+
constructor(x = 0, y = 0) {
|
|
18627
|
+
this.x = x;
|
|
18628
|
+
this.y = y;
|
|
18426
18629
|
}
|
|
18427
|
-
|
|
18428
|
-
|
|
18429
|
-
|
|
18430
|
-
|
|
18431
|
-
|
|
18432
|
-
|
|
18433
|
-
|
|
18630
|
+
/**
|
|
18631
|
+
* Creates a copy of this vector
|
|
18632
|
+
*
|
|
18633
|
+
* @returns A new Vector2 with the same values
|
|
18634
|
+
*/
|
|
18635
|
+
clone() {
|
|
18636
|
+
return new _Vector2(this.x, this.y);
|
|
18434
18637
|
}
|
|
18435
|
-
|
|
18436
|
-
|
|
18437
|
-
|
|
18438
|
-
|
|
18439
|
-
|
|
18440
|
-
|
|
18441
|
-
|
|
18442
|
-
|
|
18443
|
-
|
|
18444
|
-
|
|
18445
|
-
|
|
18446
|
-
return newProvider;
|
|
18447
|
-
} else if (typeof provider === "object" && provider.provide === key) {
|
|
18448
|
-
return newProvider;
|
|
18449
|
-
}
|
|
18450
|
-
return provider;
|
|
18451
|
-
});
|
|
18452
|
-
if (upsert && !exists) {
|
|
18453
|
-
mappedProviders.push(newProvider);
|
|
18638
|
+
/**
|
|
18639
|
+
* Sets the components of this vector
|
|
18640
|
+
*
|
|
18641
|
+
* @param x - X component
|
|
18642
|
+
* @param y - Y component
|
|
18643
|
+
* @returns This vector for chaining
|
|
18644
|
+
*/
|
|
18645
|
+
set(x, y) {
|
|
18646
|
+
this.x = x;
|
|
18647
|
+
this.y = y;
|
|
18648
|
+
return this;
|
|
18454
18649
|
}
|
|
18455
|
-
|
|
18456
|
-
|
|
18457
|
-
|
|
18458
|
-
|
|
18459
|
-
|
|
18460
|
-
|
|
18461
|
-
|
|
18462
|
-
|
|
18463
|
-
|
|
18464
|
-
|
|
18465
|
-
}
|
|
18650
|
+
/**
|
|
18651
|
+
* Copies values from another vector
|
|
18652
|
+
*
|
|
18653
|
+
* @param other - Vector to copy from
|
|
18654
|
+
* @returns This vector for chaining
|
|
18655
|
+
*/
|
|
18656
|
+
copyFrom(other) {
|
|
18657
|
+
this.x = other.x;
|
|
18658
|
+
this.y = other.y;
|
|
18659
|
+
return this;
|
|
18466
18660
|
}
|
|
18467
|
-
|
|
18468
|
-
|
|
18469
|
-
|
|
18470
|
-
|
|
18471
|
-
|
|
18472
|
-
|
|
18473
|
-
|
|
18474
|
-
|
|
18475
|
-
if (name instanceof RegExp) {
|
|
18476
|
-
if (name.test(providerName)) return providers;
|
|
18477
|
-
} else {
|
|
18478
|
-
if (providerName === name) return providers;
|
|
18479
|
-
}
|
|
18480
|
-
}
|
|
18481
|
-
return null;
|
|
18661
|
+
/**
|
|
18662
|
+
* Adds another vector to this vector (immutable)
|
|
18663
|
+
*
|
|
18664
|
+
* @param other - Vector to add
|
|
18665
|
+
* @returns New vector with the result
|
|
18666
|
+
*/
|
|
18667
|
+
add(other) {
|
|
18668
|
+
return new _Vector2(this.x + other.x, this.y + other.y);
|
|
18482
18669
|
}
|
|
18483
|
-
|
|
18484
|
-
|
|
18485
|
-
|
|
18486
|
-
|
|
18487
|
-
|
|
18488
|
-
|
|
18489
|
-
|
|
18490
|
-
|
|
18491
|
-
|
|
18492
|
-
|
|
18493
|
-
|
|
18494
|
-
|
|
18495
|
-
|
|
18496
|
-
|
|
18670
|
+
/**
|
|
18671
|
+
* Adds another vector to this vector (in-place)
|
|
18672
|
+
*
|
|
18673
|
+
* @param other - Vector to add
|
|
18674
|
+
* @returns This vector for chaining
|
|
18675
|
+
*/
|
|
18676
|
+
addInPlace(other) {
|
|
18677
|
+
this.x += other.x;
|
|
18678
|
+
this.y += other.y;
|
|
18679
|
+
return this;
|
|
18680
|
+
}
|
|
18681
|
+
/**
|
|
18682
|
+
* Subtracts another vector from this vector (immutable)
|
|
18683
|
+
*
|
|
18684
|
+
* @param other - Vector to subtract
|
|
18685
|
+
* @returns New vector with the result
|
|
18686
|
+
*/
|
|
18687
|
+
sub(other) {
|
|
18688
|
+
return new _Vector2(this.x - other.x, this.y - other.y);
|
|
18689
|
+
}
|
|
18690
|
+
/**
|
|
18691
|
+
* Subtracts another vector from this vector (in-place)
|
|
18692
|
+
*
|
|
18693
|
+
* @param other - Vector to subtract
|
|
18694
|
+
* @returns This vector for chaining
|
|
18695
|
+
*/
|
|
18696
|
+
subInPlace(other) {
|
|
18697
|
+
this.x -= other.x;
|
|
18698
|
+
this.y -= other.y;
|
|
18699
|
+
return this;
|
|
18700
|
+
}
|
|
18701
|
+
/**
|
|
18702
|
+
* Multiplies this vector by a scalar (immutable)
|
|
18703
|
+
*
|
|
18704
|
+
* @param scalar - Scalar value
|
|
18705
|
+
* @returns New vector with the result
|
|
18706
|
+
*/
|
|
18707
|
+
mul(scalar) {
|
|
18708
|
+
return new _Vector2(this.x * scalar, this.y * scalar);
|
|
18709
|
+
}
|
|
18710
|
+
/**
|
|
18711
|
+
* Multiplies this vector by a scalar (in-place)
|
|
18712
|
+
*
|
|
18713
|
+
* @param scalar - Scalar value
|
|
18714
|
+
* @returns This vector for chaining
|
|
18715
|
+
*/
|
|
18716
|
+
mulInPlace(scalar) {
|
|
18717
|
+
this.x *= scalar;
|
|
18718
|
+
this.y *= scalar;
|
|
18719
|
+
return this;
|
|
18720
|
+
}
|
|
18721
|
+
/**
|
|
18722
|
+
* Divides this vector by a scalar (immutable)
|
|
18723
|
+
*
|
|
18724
|
+
* @param scalar - Scalar value (must not be zero)
|
|
18725
|
+
* @returns New vector with the result
|
|
18726
|
+
*/
|
|
18727
|
+
div(scalar) {
|
|
18728
|
+
return new _Vector2(this.x / scalar, this.y / scalar);
|
|
18729
|
+
}
|
|
18730
|
+
/**
|
|
18731
|
+
* Divides this vector by a scalar (in-place)
|
|
18732
|
+
*
|
|
18733
|
+
* @param scalar - Scalar value (must not be zero)
|
|
18734
|
+
* @returns This vector for chaining
|
|
18735
|
+
*/
|
|
18736
|
+
divInPlace(scalar) {
|
|
18737
|
+
this.x /= scalar;
|
|
18738
|
+
this.y /= scalar;
|
|
18739
|
+
return this;
|
|
18740
|
+
}
|
|
18741
|
+
/**
|
|
18742
|
+
* Calculates the dot product with another vector
|
|
18743
|
+
*
|
|
18744
|
+
* @param other - Vector to dot with
|
|
18745
|
+
* @returns Dot product value
|
|
18746
|
+
*/
|
|
18747
|
+
dot(other) {
|
|
18748
|
+
return this.x * other.x + this.y * other.y;
|
|
18749
|
+
}
|
|
18750
|
+
/**
|
|
18751
|
+
* Calculates the 2D cross product (scalar result)
|
|
18752
|
+
*
|
|
18753
|
+
* @param other - Vector to cross with
|
|
18754
|
+
* @returns Cross product value (z-component of 3D cross product)
|
|
18755
|
+
*/
|
|
18756
|
+
cross(other) {
|
|
18757
|
+
return this.x * other.y - this.y * other.x;
|
|
18758
|
+
}
|
|
18759
|
+
/**
|
|
18760
|
+
* Calculates the squared length (faster than length, avoids sqrt)
|
|
18761
|
+
*
|
|
18762
|
+
* @returns Squared length
|
|
18763
|
+
*/
|
|
18764
|
+
lengthSquared() {
|
|
18765
|
+
return this.x * this.x + this.y * this.y;
|
|
18766
|
+
}
|
|
18767
|
+
/**
|
|
18768
|
+
* Calculates the length (magnitude) of the vector
|
|
18769
|
+
*
|
|
18770
|
+
* @returns Length
|
|
18771
|
+
*/
|
|
18772
|
+
length() {
|
|
18773
|
+
return Math.sqrt(this.lengthSquared());
|
|
18774
|
+
}
|
|
18775
|
+
/**
|
|
18776
|
+
* Normalizes this vector to unit length (immutable)
|
|
18777
|
+
*
|
|
18778
|
+
* @returns New normalized vector
|
|
18779
|
+
*/
|
|
18780
|
+
normalize() {
|
|
18781
|
+
const len = this.length();
|
|
18782
|
+
if (len === 0) {
|
|
18783
|
+
return new _Vector2(0, 0);
|
|
18784
|
+
}
|
|
18785
|
+
return this.div(len);
|
|
18786
|
+
}
|
|
18787
|
+
/**
|
|
18788
|
+
* Normalizes this vector to unit length (in-place)
|
|
18789
|
+
*
|
|
18790
|
+
* @returns This vector for chaining
|
|
18791
|
+
*/
|
|
18792
|
+
normalizeInPlace() {
|
|
18793
|
+
const len = this.length();
|
|
18794
|
+
if (len === 0) {
|
|
18795
|
+
this.x = 0;
|
|
18796
|
+
this.y = 0;
|
|
18797
|
+
} else {
|
|
18798
|
+
this.divInPlace(len);
|
|
18799
|
+
}
|
|
18800
|
+
return this;
|
|
18801
|
+
}
|
|
18802
|
+
/**
|
|
18803
|
+
* Calculates the distance to another vector
|
|
18804
|
+
*
|
|
18805
|
+
* @param other - Target vector
|
|
18806
|
+
* @returns Distance
|
|
18807
|
+
*/
|
|
18808
|
+
distanceTo(other) {
|
|
18809
|
+
return this.sub(other).length();
|
|
18810
|
+
}
|
|
18811
|
+
/**
|
|
18812
|
+
* Calculates the squared distance to another vector (faster)
|
|
18813
|
+
*
|
|
18814
|
+
* @param other - Target vector
|
|
18815
|
+
* @returns Squared distance
|
|
18816
|
+
*/
|
|
18817
|
+
distanceToSquared(other) {
|
|
18818
|
+
return this.sub(other).lengthSquared();
|
|
18819
|
+
}
|
|
18820
|
+
/**
|
|
18821
|
+
* Rotates this vector by an angle in radians (immutable)
|
|
18822
|
+
*
|
|
18823
|
+
* @param angle - Angle in radians
|
|
18824
|
+
* @returns New rotated vector
|
|
18825
|
+
*/
|
|
18826
|
+
rotate(angle) {
|
|
18827
|
+
const cos = Math.cos(angle);
|
|
18828
|
+
const sin = Math.sin(angle);
|
|
18829
|
+
return new _Vector2(
|
|
18830
|
+
this.x * cos - this.y * sin,
|
|
18831
|
+
this.x * sin + this.y * cos
|
|
18832
|
+
);
|
|
18833
|
+
}
|
|
18834
|
+
/**
|
|
18835
|
+
* Rotates this vector by an angle in radians (in-place)
|
|
18836
|
+
*
|
|
18837
|
+
* @param angle - Angle in radians
|
|
18838
|
+
* @returns This vector for chaining
|
|
18839
|
+
*/
|
|
18840
|
+
rotateInPlace(angle) {
|
|
18841
|
+
const cos = Math.cos(angle);
|
|
18842
|
+
const sin = Math.sin(angle);
|
|
18843
|
+
const x = this.x * cos - this.y * sin;
|
|
18844
|
+
const y = this.x * sin + this.y * cos;
|
|
18845
|
+
this.x = x;
|
|
18846
|
+
this.y = y;
|
|
18847
|
+
return this;
|
|
18848
|
+
}
|
|
18849
|
+
/**
|
|
18850
|
+
* Calculates the angle of this vector in radians
|
|
18851
|
+
*
|
|
18852
|
+
* @returns Angle in radians (range: -π to π)
|
|
18853
|
+
*/
|
|
18854
|
+
angle() {
|
|
18855
|
+
return Math.atan2(this.y, this.x);
|
|
18856
|
+
}
|
|
18857
|
+
/**
|
|
18858
|
+
* Linearly interpolates between this vector and another
|
|
18859
|
+
*
|
|
18860
|
+
* @param other - Target vector
|
|
18861
|
+
* @param t - Interpolation factor (0 to 1)
|
|
18862
|
+
* @returns New interpolated vector
|
|
18863
|
+
*/
|
|
18864
|
+
lerp(other, t) {
|
|
18865
|
+
return new _Vector2(
|
|
18866
|
+
this.x + (other.x - this.x) * t,
|
|
18867
|
+
this.y + (other.y - this.y) * t
|
|
18868
|
+
);
|
|
18869
|
+
}
|
|
18870
|
+
/**
|
|
18871
|
+
* Checks if this vector equals another (with epsilon tolerance)
|
|
18872
|
+
*
|
|
18873
|
+
* @param other - Vector to compare
|
|
18874
|
+
* @param epsilon - Tolerance for comparison (default: 1e-5)
|
|
18875
|
+
* @returns True if vectors are approximately equal
|
|
18876
|
+
*/
|
|
18877
|
+
equals(other, epsilon = 1e-5) {
|
|
18878
|
+
return Math.abs(this.x - other.x) < epsilon && Math.abs(this.y - other.y) < epsilon;
|
|
18879
|
+
}
|
|
18880
|
+
/**
|
|
18881
|
+
* Returns a string representation of this vector
|
|
18882
|
+
*
|
|
18883
|
+
* @returns String representation
|
|
18884
|
+
*/
|
|
18885
|
+
toString() {
|
|
18886
|
+
return `Vector2(${this.x}, ${this.y})`;
|
|
18887
|
+
}
|
|
18888
|
+
};
|
|
18889
|
+
_Vector2.ZERO = new _Vector2(0, 0);
|
|
18890
|
+
_Vector2.UNIT_X = new _Vector2(1, 0);
|
|
18891
|
+
_Vector2.UNIT_Y = new _Vector2(0, 1);
|
|
18892
|
+
let Vector2 = _Vector2;
|
|
18893
|
+
|
|
18894
|
+
var EntityState = /* @__PURE__ */ ((EntityState2) => {
|
|
18895
|
+
EntityState2[EntityState2["Static"] = 1] = "Static";
|
|
18896
|
+
EntityState2[EntityState2["Dynamic"] = 2] = "Dynamic";
|
|
18897
|
+
EntityState2[EntityState2["Sleeping"] = 4] = "Sleeping";
|
|
18898
|
+
EntityState2[EntityState2["Kinematic"] = 8] = "Kinematic";
|
|
18899
|
+
return EntityState2;
|
|
18900
|
+
})(EntityState || {});
|
|
18901
|
+
|
|
18902
|
+
function WithComponentManager(Base) {
|
|
18903
|
+
return class extends Base {
|
|
18904
|
+
setGraphic(graphic) {
|
|
18905
|
+
if (Array.isArray(graphic)) {
|
|
18906
|
+
this.graphics.set(graphic);
|
|
18907
|
+
} else {
|
|
18908
|
+
this.graphics.set([graphic]);
|
|
18909
|
+
}
|
|
18910
|
+
}
|
|
18911
|
+
/**
|
|
18912
|
+
* Set components to display above the player graphic
|
|
18913
|
+
*
|
|
18914
|
+
* Components are displayed above the player's sprite and can include
|
|
18915
|
+
* text, bars, shapes, or any combination. The components are synchronized
|
|
18916
|
+
* to all clients on the map.
|
|
18917
|
+
*
|
|
18918
|
+
* @param layout - Component(s) to display, can be single, array, or 2D array
|
|
18919
|
+
* @param options - Optional layout options for positioning and sizing
|
|
18920
|
+
* @returns void
|
|
18921
|
+
*
|
|
18922
|
+
* @example
|
|
18923
|
+
* ```ts
|
|
18924
|
+
* // Single text component
|
|
18925
|
+
* player.setComponentsTop(Components.text('{name}'));
|
|
18926
|
+
*
|
|
18927
|
+
* // Multiple components vertically
|
|
18928
|
+
* player.setComponentsTop([
|
|
18929
|
+
* Components.text('HP: {hp}'),
|
|
18930
|
+
* Components.text('{name}')
|
|
18931
|
+
* ]);
|
|
18932
|
+
*
|
|
18933
|
+
* // Table layout (columns)
|
|
18934
|
+
* player.setComponentsTop([
|
|
18935
|
+
* [Components.text('{hp}'), Components.text('{name}')]
|
|
18936
|
+
* ]);
|
|
18937
|
+
*
|
|
18938
|
+
* // With layout options
|
|
18939
|
+
* player.setComponentsTop([
|
|
18940
|
+
* Components.text('HP: {hp}'),
|
|
18941
|
+
* Components.text('{name}')
|
|
18942
|
+
* ], {
|
|
18943
|
+
* width: 100,
|
|
18944
|
+
* height: 30,
|
|
18945
|
+
* marginBottom: -10
|
|
18946
|
+
* });
|
|
18947
|
+
* ```
|
|
18948
|
+
*/
|
|
18949
|
+
setComponentsTop(layout, options) {
|
|
18950
|
+
const normalized = this.normalizeComponents(layout);
|
|
18951
|
+
const data = {
|
|
18952
|
+
components: normalized,
|
|
18953
|
+
layout: options || {}
|
|
18954
|
+
};
|
|
18955
|
+
this.componentsTop.set(JSON.stringify(data));
|
|
18956
|
+
}
|
|
18957
|
+
/**
|
|
18958
|
+
* Set components to display below the player graphic
|
|
18959
|
+
*
|
|
18960
|
+
* Components are displayed below the player's sprite and can include
|
|
18961
|
+
* text, bars, shapes, or any combination. The components are synchronized
|
|
18962
|
+
* to all clients on the map.
|
|
18963
|
+
*
|
|
18964
|
+
* @param layout - Component(s) to display, can be single, array, or 2D array
|
|
18965
|
+
* @param options - Optional layout options for positioning and sizing
|
|
18966
|
+
* @returns void
|
|
18967
|
+
*
|
|
18968
|
+
* @example
|
|
18969
|
+
* ```ts
|
|
18970
|
+
* player.setComponentsBottom(Components.shape({
|
|
18971
|
+
* fill: '#ff0000',
|
|
18972
|
+
* type: 'rectangle',
|
|
18973
|
+
* width: 32,
|
|
18974
|
+
* height: 32
|
|
18975
|
+
* }), {
|
|
18976
|
+
* marginBottom: 16
|
|
18977
|
+
* });
|
|
18978
|
+
* ```
|
|
18979
|
+
*/
|
|
18980
|
+
setComponentsBottom(layout, options) {
|
|
18981
|
+
const normalized = this.normalizeComponents(layout);
|
|
18982
|
+
const data = {
|
|
18983
|
+
components: normalized,
|
|
18984
|
+
layout: options || {}
|
|
18985
|
+
};
|
|
18986
|
+
this.componentsBottom.set(JSON.stringify(data));
|
|
18987
|
+
}
|
|
18988
|
+
/**
|
|
18989
|
+
* Set components to display at the center of the player graphic
|
|
18990
|
+
*
|
|
18991
|
+
* Components are displayed at the center of the player's sprite.
|
|
18992
|
+
* Be careful: if you assign, it deletes the graphics and if the lines are superimposed.
|
|
18993
|
+
*
|
|
18994
|
+
* @param layout - Component(s) to display, can be single, array, or 2D array
|
|
18995
|
+
* @param options - Optional layout options for positioning and sizing
|
|
18996
|
+
* @returns void
|
|
18997
|
+
*
|
|
18998
|
+
* @example
|
|
18999
|
+
* ```ts
|
|
19000
|
+
* player.setComponentsCenter([
|
|
19001
|
+
* Components.text('{name}'),
|
|
19002
|
+
* Components.hpBar()
|
|
19003
|
+
* ]);
|
|
19004
|
+
* ```
|
|
19005
|
+
*/
|
|
19006
|
+
setComponentsCenter(layout, options) {
|
|
19007
|
+
const normalized = this.normalizeComponents(layout);
|
|
19008
|
+
const data = {
|
|
19009
|
+
components: normalized,
|
|
19010
|
+
layout: options || {}
|
|
19011
|
+
};
|
|
19012
|
+
this.componentsCenter.set(JSON.stringify(data));
|
|
19013
|
+
}
|
|
19014
|
+
/**
|
|
19015
|
+
* Set components to display to the left of the player graphic
|
|
19016
|
+
*
|
|
19017
|
+
* Components are displayed to the left of the player's sprite.
|
|
19018
|
+
*
|
|
19019
|
+
* @param layout - Component(s) to display, can be single, array, or 2D array
|
|
19020
|
+
* @param options - Optional layout options for positioning and sizing
|
|
19021
|
+
* @returns void
|
|
19022
|
+
*
|
|
19023
|
+
* @example
|
|
19024
|
+
* ```ts
|
|
19025
|
+
* player.setComponentsLeft([
|
|
19026
|
+
* Components.text('{name}'),
|
|
19027
|
+
* Components.hpBar()
|
|
19028
|
+
* ]);
|
|
19029
|
+
* ```
|
|
19030
|
+
*/
|
|
19031
|
+
setComponentsLeft(layout, options) {
|
|
19032
|
+
const normalized = this.normalizeComponents(layout);
|
|
19033
|
+
const data = {
|
|
19034
|
+
components: normalized,
|
|
19035
|
+
layout: options || {}
|
|
19036
|
+
};
|
|
19037
|
+
this.componentsLeft.set(JSON.stringify(data));
|
|
19038
|
+
}
|
|
19039
|
+
/**
|
|
19040
|
+
* Set components to display to the right of the player graphic
|
|
19041
|
+
*
|
|
19042
|
+
* Components are displayed to the right of the player's sprite.
|
|
19043
|
+
*
|
|
19044
|
+
* @param layout - Component(s) to display, can be single, array, or 2D array
|
|
19045
|
+
* @param options - Optional layout options for positioning and sizing
|
|
19046
|
+
* @returns void
|
|
19047
|
+
*
|
|
19048
|
+
* @example
|
|
19049
|
+
* ```ts
|
|
19050
|
+
* player.setComponentsRight([
|
|
19051
|
+
* Components.text('{name}'),
|
|
19052
|
+
* Components.hpBar()
|
|
19053
|
+
* ]);
|
|
19054
|
+
* ```
|
|
19055
|
+
*/
|
|
19056
|
+
setComponentsRight(layout, options) {
|
|
19057
|
+
const normalized = this.normalizeComponents(layout);
|
|
19058
|
+
const data = {
|
|
19059
|
+
components: normalized,
|
|
19060
|
+
layout: options || {}
|
|
19061
|
+
};
|
|
19062
|
+
this.componentsRight.set(JSON.stringify(data));
|
|
19063
|
+
}
|
|
19064
|
+
/**
|
|
19065
|
+
* Remove components from a specific position
|
|
19066
|
+
*
|
|
19067
|
+
* Deletes all components at the specified position.
|
|
19068
|
+
*
|
|
19069
|
+
* @param position - Position of the components: 'top', 'center', 'bottom', 'left', or 'right'
|
|
19070
|
+
* @returns void
|
|
19071
|
+
*
|
|
19072
|
+
* @example
|
|
19073
|
+
* ```ts
|
|
19074
|
+
* player.removeComponents('top');
|
|
19075
|
+
* ```
|
|
19076
|
+
*/
|
|
19077
|
+
removeComponents(position) {
|
|
19078
|
+
switch (position) {
|
|
19079
|
+
case "top":
|
|
19080
|
+
this.componentsTop.set(null);
|
|
19081
|
+
break;
|
|
19082
|
+
case "center":
|
|
19083
|
+
this.componentsCenter.set(null);
|
|
19084
|
+
break;
|
|
19085
|
+
case "bottom":
|
|
19086
|
+
this.componentsBottom.set(null);
|
|
19087
|
+
break;
|
|
19088
|
+
case "left":
|
|
19089
|
+
this.componentsLeft.set(null);
|
|
19090
|
+
break;
|
|
19091
|
+
case "right":
|
|
19092
|
+
this.componentsRight.set(null);
|
|
19093
|
+
break;
|
|
19094
|
+
}
|
|
19095
|
+
}
|
|
19096
|
+
/**
|
|
19097
|
+
* Merge components with existing components at a specific position
|
|
19098
|
+
*
|
|
19099
|
+
* Merges new components with existing components at the specified position.
|
|
19100
|
+
*
|
|
19101
|
+
* @param position - Position of the components: 'top', 'center', 'bottom', 'left', or 'right'
|
|
19102
|
+
* @param layout - Component(s) to merge, can be single, array, or 2D array
|
|
19103
|
+
* @param options - Optional layout options for positioning and sizing
|
|
19104
|
+
* @returns void
|
|
19105
|
+
*
|
|
19106
|
+
* @example
|
|
19107
|
+
* ```ts
|
|
19108
|
+
* // First set some components
|
|
19109
|
+
* player.setComponentsTop([Components.text('{name}')]);
|
|
19110
|
+
*
|
|
19111
|
+
* // Then merge additional components
|
|
19112
|
+
* player.mergeComponents('top', [Components.hpBar()], {
|
|
19113
|
+
* width: 100
|
|
19114
|
+
* });
|
|
19115
|
+
* ```
|
|
19116
|
+
*/
|
|
19117
|
+
mergeComponents(position, layout, options) {
|
|
19118
|
+
const normalized = this.normalizeComponents(layout);
|
|
19119
|
+
let existingData = null;
|
|
19120
|
+
let signal = null;
|
|
19121
|
+
switch (position) {
|
|
19122
|
+
case "top":
|
|
19123
|
+
signal = this.componentsTop;
|
|
19124
|
+
break;
|
|
19125
|
+
case "center":
|
|
19126
|
+
signal = this.componentsCenter;
|
|
19127
|
+
break;
|
|
19128
|
+
case "bottom":
|
|
19129
|
+
signal = this.componentsBottom;
|
|
19130
|
+
break;
|
|
19131
|
+
case "left":
|
|
19132
|
+
signal = this.componentsLeft;
|
|
19133
|
+
break;
|
|
19134
|
+
case "right":
|
|
19135
|
+
signal = this.componentsRight;
|
|
19136
|
+
break;
|
|
19137
|
+
}
|
|
19138
|
+
const existingJson = signal();
|
|
19139
|
+
if (existingJson) {
|
|
19140
|
+
try {
|
|
19141
|
+
existingData = JSON.parse(existingJson);
|
|
19142
|
+
} catch (e) {
|
|
19143
|
+
existingData = null;
|
|
19144
|
+
}
|
|
19145
|
+
}
|
|
19146
|
+
const existingComponents = existingData?.components || [];
|
|
19147
|
+
const mergedComponents = [...existingComponents, ...normalized];
|
|
19148
|
+
const mergedLayout = {
|
|
19149
|
+
...existingData?.layout || {},
|
|
19150
|
+
...options || {}
|
|
19151
|
+
};
|
|
19152
|
+
const data = {
|
|
19153
|
+
components: mergedComponents,
|
|
19154
|
+
layout: mergedLayout
|
|
19155
|
+
};
|
|
19156
|
+
signal.set(JSON.stringify(data));
|
|
19157
|
+
}
|
|
19158
|
+
/**
|
|
19159
|
+
* Normalize component input to a consistent structure
|
|
19160
|
+
*
|
|
19161
|
+
* Converts various input formats (single component, array, 2D array)
|
|
19162
|
+
* into a normalized 2D array structure for consistent rendering.
|
|
19163
|
+
*
|
|
19164
|
+
* @param components - Component input in any format
|
|
19165
|
+
* @returns Normalized 2D array of components
|
|
19166
|
+
*/
|
|
19167
|
+
normalizeComponents(components) {
|
|
19168
|
+
if (!components) {
|
|
19169
|
+
return [];
|
|
19170
|
+
}
|
|
19171
|
+
if (!Array.isArray(components)) {
|
|
19172
|
+
return [[components]];
|
|
19173
|
+
}
|
|
19174
|
+
if (components.length > 0 && Array.isArray(components[0])) {
|
|
19175
|
+
return components;
|
|
19176
|
+
}
|
|
19177
|
+
return components.map((comp) => [comp]);
|
|
19178
|
+
}
|
|
19179
|
+
};
|
|
19180
|
+
}
|
|
19181
|
+
|
|
19182
|
+
var __defProp$3 = Object.defineProperty;
|
|
19183
|
+
var __name = (target, value) => __defProp$3(target, "name", { value, configurable: true });
|
|
19184
|
+
|
|
19185
|
+
// src/inject.ts
|
|
19186
|
+
function provide(context, name, value) {
|
|
19187
|
+
context.set("inject:" + name, value);
|
|
19188
|
+
return value;
|
|
19189
|
+
}
|
|
19190
|
+
__name(provide, "provide");
|
|
19191
|
+
function isInjected(context, name) {
|
|
19192
|
+
return context.get("injected:" + name) === true;
|
|
19193
|
+
}
|
|
19194
|
+
__name(isInjected, "isInjected");
|
|
19195
|
+
function isProvided(context, name) {
|
|
19196
|
+
return context.get("inject:" + name) !== void 0;
|
|
19197
|
+
}
|
|
19198
|
+
__name(isProvided, "isProvided");
|
|
19199
|
+
function inject$1(context, service, args = []) {
|
|
19200
|
+
const isClass = typeof service === "function";
|
|
19201
|
+
const name = isClass ? service.name : service;
|
|
19202
|
+
const value = context.get("inject:" + name);
|
|
19203
|
+
if (value) {
|
|
19204
|
+
context.set("injected:" + name, true);
|
|
19205
|
+
return value;
|
|
19206
|
+
}
|
|
19207
|
+
throw new Error(`Injection provider ${name} not found`);
|
|
19208
|
+
}
|
|
19209
|
+
__name(inject$1, "inject");
|
|
19210
|
+
function override(providers, newProvider, options) {
|
|
19211
|
+
let { upsert = false, key } = options ?? {};
|
|
19212
|
+
if (!key) {
|
|
19213
|
+
key = typeof newProvider === "function" ? newProvider.name : newProvider.provide;
|
|
19214
|
+
}
|
|
19215
|
+
const flatProviders = providers.flat();
|
|
19216
|
+
const exists = flatProviders.some((provider) => {
|
|
19217
|
+
if (typeof provider === "function") {
|
|
19218
|
+
return provider.name === key;
|
|
19219
|
+
} else if (typeof provider === "object") {
|
|
19220
|
+
return provider.provide === key;
|
|
19221
|
+
}
|
|
19222
|
+
return false;
|
|
19223
|
+
});
|
|
19224
|
+
const mappedProviders = flatProviders.map((provider) => {
|
|
19225
|
+
if (typeof provider === "function" && provider.name === key) {
|
|
19226
|
+
return newProvider;
|
|
19227
|
+
} else if (typeof provider === "object" && provider.provide === key) {
|
|
19228
|
+
return newProvider;
|
|
19229
|
+
}
|
|
19230
|
+
return provider;
|
|
19231
|
+
});
|
|
19232
|
+
if (upsert && !exists) {
|
|
19233
|
+
mappedProviders.push(newProvider);
|
|
19234
|
+
}
|
|
19235
|
+
return mappedProviders;
|
|
19236
|
+
}
|
|
19237
|
+
__name(override, "override");
|
|
19238
|
+
function findProviders(providers, name) {
|
|
19239
|
+
const results = [];
|
|
19240
|
+
for (const provider of providers) {
|
|
19241
|
+
if (Array.isArray(provider)) {
|
|
19242
|
+
results.push(...findProviders(provider, name));
|
|
19243
|
+
} else if (findProvider(provider, name)) {
|
|
19244
|
+
results.push(provider);
|
|
19245
|
+
}
|
|
19246
|
+
}
|
|
19247
|
+
return results;
|
|
19248
|
+
}
|
|
19249
|
+
__name(findProviders, "findProviders");
|
|
19250
|
+
function findProvider(providers, name) {
|
|
19251
|
+
if (!Array.isArray(providers)) {
|
|
19252
|
+
if (typeof providers === "object" && "provide" in providers) {
|
|
19253
|
+
const provider = providers;
|
|
19254
|
+
const providerName = typeof provider.provide === "function" ? provider.provide.name : provider.provide;
|
|
19255
|
+
if (name instanceof RegExp) {
|
|
19256
|
+
if (name.test(providerName)) return providers;
|
|
19257
|
+
} else {
|
|
19258
|
+
if (providerName === name) return providers;
|
|
19259
|
+
}
|
|
19260
|
+
}
|
|
19261
|
+
return null;
|
|
19262
|
+
}
|
|
19263
|
+
for (const provider of providers) {
|
|
19264
|
+
if (Array.isArray(provider)) {
|
|
19265
|
+
const found = findProvider(provider, name);
|
|
19266
|
+
if (found) return found;
|
|
19267
|
+
continue;
|
|
19268
|
+
}
|
|
19269
|
+
if (typeof provider === "object" && "provide" in provider) {
|
|
19270
|
+
const providerName = typeof provider.provide === "function" ? provider.provide.name : provider.provide;
|
|
19271
|
+
if (name instanceof RegExp) {
|
|
19272
|
+
if (name.test(providerName)) return provider;
|
|
19273
|
+
} else {
|
|
19274
|
+
if (providerName === name) return provider;
|
|
19275
|
+
}
|
|
19276
|
+
}
|
|
18497
19277
|
}
|
|
18498
19278
|
return null;
|
|
18499
19279
|
}
|
|
@@ -19173,7 +19953,7 @@ function WithMoveManager(Base) {
|
|
|
19173
19953
|
staticTarget.freeze();
|
|
19174
19954
|
map.moveManager.add(
|
|
19175
19955
|
this.id,
|
|
19176
|
-
new SeekAvoid(engine, () => staticTarget,
|
|
19956
|
+
new SeekAvoid(engine, () => staticTarget, 80, 140, 80, 48)
|
|
19177
19957
|
);
|
|
19178
19958
|
}
|
|
19179
19959
|
/**
|
|
@@ -22312,6 +23092,10 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22312
23092
|
this.conn = null;
|
|
22313
23093
|
this.touchSide = false;
|
|
22314
23094
|
// Protection against map change loops
|
|
23095
|
+
/** Internal: Shapes attached to this player */
|
|
23096
|
+
this._attachedShapes = /* @__PURE__ */ new Map();
|
|
23097
|
+
/** Internal: Shapes where this player is currently located */
|
|
23098
|
+
this._inShapes = /* @__PURE__ */ new Set();
|
|
22315
23099
|
/** Last processed client input timestamp for reconciliation */
|
|
22316
23100
|
this.lastProcessedInputTs = 0;
|
|
22317
23101
|
/** Last processed client input frame for reconciliation with server tick */
|
|
@@ -22331,12 +23115,29 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22331
23115
|
this.addParameter(DEX, DEX_CURVE);
|
|
22332
23116
|
this.addParameter(AGI, AGI_CURVE);
|
|
22333
23117
|
this.allRecovery();
|
|
23118
|
+
let lastEmitted = null;
|
|
23119
|
+
let pendingUpdate = null;
|
|
23120
|
+
let updateScheduled = false;
|
|
22334
23121
|
combineLatest$1([this.x.observable, this.y.observable]).subscribe(([x, y]) => {
|
|
22335
|
-
|
|
22336
|
-
|
|
22337
|
-
|
|
22338
|
-
|
|
22339
|
-
|
|
23122
|
+
pendingUpdate = { x, y };
|
|
23123
|
+
if (!updateScheduled) {
|
|
23124
|
+
updateScheduled = true;
|
|
23125
|
+
queueMicrotask(() => {
|
|
23126
|
+
if (pendingUpdate) {
|
|
23127
|
+
const { x: x2, y: y2 } = pendingUpdate;
|
|
23128
|
+
if (!lastEmitted || lastEmitted.x !== x2 || lastEmitted.y !== y2) {
|
|
23129
|
+
this.frames = [...this.frames, {
|
|
23130
|
+
x: x2,
|
|
23131
|
+
y: y2,
|
|
23132
|
+
ts: Date.now()
|
|
23133
|
+
}];
|
|
23134
|
+
lastEmitted = { x: x2, y: y2 };
|
|
23135
|
+
}
|
|
23136
|
+
pendingUpdate = null;
|
|
23137
|
+
}
|
|
23138
|
+
updateScheduled = false;
|
|
23139
|
+
});
|
|
23140
|
+
}
|
|
22340
23141
|
});
|
|
22341
23142
|
}
|
|
22342
23143
|
_onInit() {
|
|
@@ -22411,22 +23212,22 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22411
23212
|
* ```
|
|
22412
23213
|
*/
|
|
22413
23214
|
async autoChangeMap(nextPosition, forcedDirection) {
|
|
22414
|
-
const
|
|
22415
|
-
if (!
|
|
22416
|
-
const worldMaps =
|
|
23215
|
+
const map2 = this.getCurrentMap();
|
|
23216
|
+
if (!map2) return false;
|
|
23217
|
+
const worldMaps = map2.getWorldMapsManager?.();
|
|
22417
23218
|
let ret = false;
|
|
22418
|
-
if (worldMaps &&
|
|
23219
|
+
if (worldMaps && map2) {
|
|
22419
23220
|
const direction = forcedDirection ?? this.getDirection();
|
|
22420
|
-
const marginLeftRight = (
|
|
22421
|
-
const marginTopDown = (
|
|
22422
|
-
const worldPositionX = (
|
|
22423
|
-
const worldPositionY = (
|
|
23221
|
+
const marginLeftRight = (map2.tileWidth ?? 32) / 2;
|
|
23222
|
+
const marginTopDown = (map2.tileHeight ?? 32) / 2;
|
|
23223
|
+
const worldPositionX = (map2.worldX ?? 0) + this.x();
|
|
23224
|
+
const worldPositionY = (map2.worldY ?? 0) + this.y();
|
|
22424
23225
|
const changeMap = async (adjacentCoords, positionCalculator) => {
|
|
22425
23226
|
if (this.touchSide) {
|
|
22426
23227
|
return false;
|
|
22427
23228
|
}
|
|
22428
23229
|
this.touchSide = true;
|
|
22429
|
-
const [nextMap] = worldMaps.getAdjacentMaps(
|
|
23230
|
+
const [nextMap] = worldMaps.getAdjacentMaps(map2, adjacentCoords);
|
|
22430
23231
|
if (!nextMap) {
|
|
22431
23232
|
this.touchSide = false;
|
|
22432
23233
|
return false;
|
|
@@ -22446,34 +23247,34 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22446
23247
|
};
|
|
22447
23248
|
if (nextPosition.x < marginLeftRight && direction === Direction.Left) {
|
|
22448
23249
|
ret = await changeMap({
|
|
22449
|
-
x: (
|
|
23250
|
+
x: (map2.worldX ?? 0) - 1,
|
|
22450
23251
|
y: worldPositionY
|
|
22451
23252
|
}, (nextMapInfo) => ({
|
|
22452
23253
|
x: nextMapInfo.width - this.hitbox().w - marginLeftRight,
|
|
22453
|
-
y: (
|
|
23254
|
+
y: (map2.worldY ?? 0) - (nextMapInfo.y ?? 0) + nextPosition.y
|
|
22454
23255
|
}));
|
|
22455
|
-
} else if (nextPosition.x >
|
|
23256
|
+
} else if (nextPosition.x > map2.widthPx - this.hitbox().w - marginLeftRight && direction === Direction.Right) {
|
|
22456
23257
|
ret = await changeMap({
|
|
22457
|
-
x: (
|
|
23258
|
+
x: (map2.worldX ?? 0) + map2.widthPx + 1,
|
|
22458
23259
|
y: worldPositionY
|
|
22459
23260
|
}, (nextMapInfo) => ({
|
|
22460
23261
|
x: marginLeftRight,
|
|
22461
|
-
y: (
|
|
23262
|
+
y: (map2.worldY ?? 0) - (nextMapInfo.y ?? 0) + nextPosition.y
|
|
22462
23263
|
}));
|
|
22463
23264
|
} else if (nextPosition.y < marginTopDown && direction === Direction.Up) {
|
|
22464
23265
|
ret = await changeMap({
|
|
22465
23266
|
x: worldPositionX,
|
|
22466
|
-
y: (
|
|
23267
|
+
y: (map2.worldY ?? 0) - 1
|
|
22467
23268
|
}, (nextMapInfo) => ({
|
|
22468
|
-
x: (
|
|
23269
|
+
x: (map2.worldX ?? 0) - (nextMapInfo.x ?? 0) + nextPosition.x,
|
|
22469
23270
|
y: nextMapInfo.height - this.hitbox().h - marginTopDown
|
|
22470
23271
|
}));
|
|
22471
|
-
} else if (nextPosition.y >
|
|
23272
|
+
} else if (nextPosition.y > map2.heightPx - this.hitbox().h - marginTopDown && direction === Direction.Down) {
|
|
22472
23273
|
ret = await changeMap({
|
|
22473
23274
|
x: worldPositionX,
|
|
22474
|
-
y: (
|
|
23275
|
+
y: (map2.worldY ?? 0) + map2.heightPx + 1
|
|
22475
23276
|
}, (nextMapInfo) => ({
|
|
22476
|
-
x: (
|
|
23277
|
+
x: (map2.worldX ?? 0) - (nextMapInfo.x ?? 0) + nextPosition.x,
|
|
22477
23278
|
y: marginTopDown
|
|
22478
23279
|
}));
|
|
22479
23280
|
} else {
|
|
@@ -22493,15 +23294,17 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22493
23294
|
this.x.set(positions.x);
|
|
22494
23295
|
this.y.set(positions.y);
|
|
22495
23296
|
}
|
|
22496
|
-
|
|
23297
|
+
queueMicrotask(() => {
|
|
23298
|
+
this.applyFrames();
|
|
23299
|
+
});
|
|
22497
23300
|
}
|
|
22498
23301
|
getCurrentMap() {
|
|
22499
23302
|
return this.map;
|
|
22500
23303
|
}
|
|
22501
23304
|
emit(type2, value) {
|
|
22502
|
-
const
|
|
22503
|
-
if (!
|
|
22504
|
-
|
|
23305
|
+
const map2 = this.getCurrentMap();
|
|
23306
|
+
if (!map2 || !this.conn) return;
|
|
23307
|
+
map2.$send(this.conn, {
|
|
22505
23308
|
type: type2,
|
|
22506
23309
|
value
|
|
22507
23310
|
});
|
|
@@ -22544,12 +23347,12 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22544
23347
|
* ```
|
|
22545
23348
|
*/
|
|
22546
23349
|
setAnimation(animationName, nbTimes = Infinity) {
|
|
22547
|
-
const
|
|
22548
|
-
if (!
|
|
23350
|
+
const map2 = this.getCurrentMap();
|
|
23351
|
+
if (!map2) return;
|
|
22549
23352
|
if (nbTimes === Infinity) {
|
|
22550
23353
|
this.animationName.set(animationName);
|
|
22551
23354
|
} else {
|
|
22552
|
-
|
|
23355
|
+
map2.$broadcast({
|
|
22553
23356
|
type: "setAnimation",
|
|
22554
23357
|
value: {
|
|
22555
23358
|
animationName,
|
|
@@ -22572,9 +23375,9 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22572
23375
|
this._eventChanges();
|
|
22573
23376
|
}
|
|
22574
23377
|
databaseById(id) {
|
|
22575
|
-
const
|
|
22576
|
-
if (!
|
|
22577
|
-
const data =
|
|
23378
|
+
const map2 = this.getCurrentMap();
|
|
23379
|
+
if (!map2) return;
|
|
23380
|
+
const data = map2.database()[id];
|
|
22578
23381
|
if (!data)
|
|
22579
23382
|
throw new Error(
|
|
22580
23383
|
`The ID=${id} data is not found in the database. Add the data in the property "database"`
|
|
@@ -22582,9 +23385,9 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22582
23385
|
return data;
|
|
22583
23386
|
}
|
|
22584
23387
|
_eventChanges() {
|
|
22585
|
-
const
|
|
22586
|
-
if (!
|
|
22587
|
-
const { events } =
|
|
23388
|
+
const map2 = this.getCurrentMap();
|
|
23389
|
+
if (!map2) return;
|
|
23390
|
+
const { events } = map2;
|
|
22588
23391
|
const arrayEvents = [
|
|
22589
23392
|
...Object.values(this.events()),
|
|
22590
23393
|
...Object.values(events?.() ?? {})
|
|
@@ -22593,39 +23396,231 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22593
23396
|
if (event.onChanges) event.onChanges(this);
|
|
22594
23397
|
}
|
|
22595
23398
|
}
|
|
22596
|
-
|
|
22597
|
-
|
|
22598
|
-
|
|
22599
|
-
|
|
22600
|
-
|
|
22601
|
-
|
|
22602
|
-
|
|
22603
|
-
|
|
22604
|
-
|
|
22605
|
-
|
|
22606
|
-
|
|
22607
|
-
|
|
22608
|
-
|
|
22609
|
-
|
|
22610
|
-
|
|
22611
|
-
|
|
22612
|
-
|
|
22613
|
-
|
|
22614
|
-
|
|
22615
|
-
|
|
23399
|
+
/**
|
|
23400
|
+
* Attach a zone shape to this player using the physic zone system
|
|
23401
|
+
*
|
|
23402
|
+
* This method creates a zone attached to the player's entity in the physics engine.
|
|
23403
|
+
* The zone can be circular or cone-shaped and will detect other entities (players/events)
|
|
23404
|
+
* entering or exiting the zone.
|
|
23405
|
+
*
|
|
23406
|
+
* @param id - Optional zone identifier. If not provided, a unique ID will be generated
|
|
23407
|
+
* @param options - Zone configuration options
|
|
23408
|
+
*
|
|
23409
|
+
* @example
|
|
23410
|
+
* ```ts
|
|
23411
|
+
* // Create a circular detection zone
|
|
23412
|
+
* player.attachShape("vision", {
|
|
23413
|
+
* radius: 150,
|
|
23414
|
+
* angle: 360,
|
|
23415
|
+
* });
|
|
23416
|
+
*
|
|
23417
|
+
* // Create a cone-shaped vision zone
|
|
23418
|
+
* player.attachShape("vision", {
|
|
23419
|
+
* radius: 200,
|
|
23420
|
+
* angle: 120,
|
|
23421
|
+
* direction: Direction.Right,
|
|
23422
|
+
* limitedByWalls: true,
|
|
23423
|
+
* });
|
|
23424
|
+
*
|
|
23425
|
+
* // Create a zone with width/height (radius calculated automatically)
|
|
23426
|
+
* player.attachShape({
|
|
23427
|
+
* width: 100,
|
|
23428
|
+
* height: 100,
|
|
23429
|
+
* positioning: "center",
|
|
23430
|
+
* });
|
|
23431
|
+
* ```
|
|
23432
|
+
*/
|
|
23433
|
+
attachShape(idOrOptions, options) {
|
|
23434
|
+
const map2 = this.getCurrentMap();
|
|
23435
|
+
if (!map2) return void 0;
|
|
23436
|
+
let zoneId;
|
|
23437
|
+
let shapeOptions;
|
|
23438
|
+
if (typeof idOrOptions === "string") {
|
|
23439
|
+
zoneId = idOrOptions;
|
|
23440
|
+
if (!options) {
|
|
23441
|
+
console.warn("attachShape: options must be provided when id is specified");
|
|
23442
|
+
return void 0;
|
|
23443
|
+
}
|
|
23444
|
+
shapeOptions = options;
|
|
23445
|
+
} else {
|
|
23446
|
+
zoneId = `zone-${this.id}-${Date.now()}`;
|
|
23447
|
+
shapeOptions = idOrOptions;
|
|
23448
|
+
}
|
|
23449
|
+
const playerEntity = map2.physic.getEntityByUUID(this.id);
|
|
23450
|
+
if (!playerEntity) {
|
|
23451
|
+
console.warn(`Player entity not found in physic engine for player ${this.id}`);
|
|
23452
|
+
return void 0;
|
|
23453
|
+
}
|
|
23454
|
+
let radius;
|
|
23455
|
+
if (shapeOptions.radius !== void 0) {
|
|
23456
|
+
radius = shapeOptions.radius;
|
|
23457
|
+
} else if (shapeOptions.width && shapeOptions.height) {
|
|
23458
|
+
radius = Math.max(shapeOptions.width, shapeOptions.height) / 2;
|
|
23459
|
+
} else {
|
|
23460
|
+
console.warn("attachShape: radius or width/height must be provided");
|
|
23461
|
+
return void 0;
|
|
23462
|
+
}
|
|
23463
|
+
let offset = new Vector2(0, 0);
|
|
23464
|
+
const positioning = shapeOptions.positioning || "default";
|
|
23465
|
+
if (shapeOptions.positioning) {
|
|
23466
|
+
const playerWidth = playerEntity.width || playerEntity.radius * 2 || 32;
|
|
23467
|
+
const playerHeight = playerEntity.height || playerEntity.radius * 2 || 32;
|
|
23468
|
+
switch (shapeOptions.positioning) {
|
|
23469
|
+
case "top":
|
|
23470
|
+
offset = new Vector2(0, -playerHeight / 2);
|
|
23471
|
+
break;
|
|
23472
|
+
case "bottom":
|
|
23473
|
+
offset = new Vector2(0, playerHeight / 2);
|
|
23474
|
+
break;
|
|
23475
|
+
case "left":
|
|
23476
|
+
offset = new Vector2(-playerWidth / 2, 0);
|
|
23477
|
+
break;
|
|
23478
|
+
case "right":
|
|
23479
|
+
offset = new Vector2(playerWidth / 2, 0);
|
|
23480
|
+
break;
|
|
23481
|
+
case "center":
|
|
23482
|
+
default:
|
|
23483
|
+
offset = new Vector2(0, 0);
|
|
23484
|
+
break;
|
|
23485
|
+
}
|
|
23486
|
+
}
|
|
23487
|
+
const zoneManager = map2.physic.getZoneManager();
|
|
23488
|
+
let direction = "down";
|
|
23489
|
+
if (shapeOptions.direction !== void 0) {
|
|
23490
|
+
if (typeof shapeOptions.direction === "string") {
|
|
23491
|
+
direction = shapeOptions.direction;
|
|
23492
|
+
} else {
|
|
23493
|
+
direction = String(shapeOptions.direction);
|
|
23494
|
+
}
|
|
23495
|
+
}
|
|
23496
|
+
const metadata = {};
|
|
23497
|
+
if (shapeOptions.name) {
|
|
23498
|
+
metadata.name = shapeOptions.name;
|
|
23499
|
+
}
|
|
23500
|
+
if (shapeOptions.properties) {
|
|
23501
|
+
metadata.properties = shapeOptions.properties;
|
|
23502
|
+
}
|
|
23503
|
+
const initialX = playerEntity.position.x + offset.x;
|
|
23504
|
+
const initialY = playerEntity.position.y + offset.y;
|
|
23505
|
+
const physicZoneId = zoneManager.createAttachedZone(
|
|
23506
|
+
playerEntity,
|
|
23507
|
+
{
|
|
23508
|
+
radius,
|
|
23509
|
+
angle: shapeOptions.angle ?? 360,
|
|
23510
|
+
direction,
|
|
23511
|
+
limitedByWalls: shapeOptions.limitedByWalls ?? false,
|
|
23512
|
+
offset,
|
|
23513
|
+
metadata: Object.keys(metadata).length > 0 ? metadata : void 0
|
|
22616
23514
|
},
|
|
22617
|
-
|
|
22618
|
-
|
|
22619
|
-
|
|
22620
|
-
|
|
22621
|
-
|
|
22622
|
-
|
|
22623
|
-
|
|
22624
|
-
|
|
22625
|
-
|
|
22626
|
-
|
|
23515
|
+
{
|
|
23516
|
+
onEnter: (entities) => {
|
|
23517
|
+
entities.forEach((entity) => {
|
|
23518
|
+
const event = map2.getEvent(entity.uuid);
|
|
23519
|
+
const player = map2.getPlayer(entity.uuid);
|
|
23520
|
+
if (event) {
|
|
23521
|
+
event.execMethod("onInShape", [shape, this]);
|
|
23522
|
+
if (event._inShapes) {
|
|
23523
|
+
event._inShapes.add(shape);
|
|
23524
|
+
}
|
|
23525
|
+
}
|
|
23526
|
+
if (player) {
|
|
23527
|
+
this.execMethod("onDetectInShape", [player, shape]);
|
|
23528
|
+
if (player._inShapes) {
|
|
23529
|
+
player._inShapes.add(shape);
|
|
23530
|
+
}
|
|
23531
|
+
}
|
|
23532
|
+
});
|
|
23533
|
+
},
|
|
23534
|
+
onExit: (entities) => {
|
|
23535
|
+
entities.forEach((entity) => {
|
|
23536
|
+
const event = map2.getEvent(entity.uuid);
|
|
23537
|
+
const player = map2.getPlayer(entity.uuid);
|
|
23538
|
+
if (event) {
|
|
23539
|
+
event.execMethod("onOutShape", [shape, this]);
|
|
23540
|
+
if (event._inShapes) {
|
|
23541
|
+
event._inShapes.delete(shape);
|
|
23542
|
+
}
|
|
23543
|
+
}
|
|
23544
|
+
if (player) {
|
|
23545
|
+
this.execMethod("onDetectOutShape", [player, shape]);
|
|
23546
|
+
if (player._inShapes) {
|
|
23547
|
+
player._inShapes.delete(shape);
|
|
23548
|
+
}
|
|
23549
|
+
}
|
|
23550
|
+
});
|
|
23551
|
+
}
|
|
22627
23552
|
}
|
|
22628
23553
|
);
|
|
23554
|
+
const shape = new RpgShape({
|
|
23555
|
+
name: shapeOptions.name || zoneId,
|
|
23556
|
+
positioning,
|
|
23557
|
+
width: shapeOptions.width || radius * 2,
|
|
23558
|
+
height: shapeOptions.height || radius * 2,
|
|
23559
|
+
x: initialX,
|
|
23560
|
+
y: initialY,
|
|
23561
|
+
properties: shapeOptions.properties || {},
|
|
23562
|
+
playerOwner: this,
|
|
23563
|
+
physicZoneId,
|
|
23564
|
+
map: map2
|
|
23565
|
+
});
|
|
23566
|
+
this._zoneIdMap = this._zoneIdMap || /* @__PURE__ */ new Map();
|
|
23567
|
+
this._zoneIdMap.set(zoneId, physicZoneId);
|
|
23568
|
+
this._attachedShapes.set(zoneId, shape);
|
|
23569
|
+
const updateShapePosition = () => {
|
|
23570
|
+
const currentEntity = map2.physic.getEntityByUUID(this.id);
|
|
23571
|
+
if (currentEntity) {
|
|
23572
|
+
const zoneInfo = zoneManager.getZone(physicZoneId);
|
|
23573
|
+
if (zoneInfo) {
|
|
23574
|
+
shape._updatePosition(zoneInfo.position.x, zoneInfo.position.y);
|
|
23575
|
+
}
|
|
23576
|
+
}
|
|
23577
|
+
};
|
|
23578
|
+
playerEntity.onPositionChange(() => {
|
|
23579
|
+
updateShapePosition();
|
|
23580
|
+
});
|
|
23581
|
+
return shape;
|
|
23582
|
+
}
|
|
23583
|
+
/**
|
|
23584
|
+
* Get all shapes attached to this player
|
|
23585
|
+
*
|
|
23586
|
+
* Returns all shapes that were created using `attachShape()` on this player.
|
|
23587
|
+
*
|
|
23588
|
+
* @returns Array of RpgShape instances attached to this player
|
|
23589
|
+
*
|
|
23590
|
+
* @example
|
|
23591
|
+
* ```ts
|
|
23592
|
+
* player.attachShape("vision", { radius: 150 });
|
|
23593
|
+
* player.attachShape("detection", { radius: 100 });
|
|
23594
|
+
*
|
|
23595
|
+
* const shapes = player.getShapes();
|
|
23596
|
+
* console.log(shapes.length); // 2
|
|
23597
|
+
* ```
|
|
23598
|
+
*/
|
|
23599
|
+
getShapes() {
|
|
23600
|
+
return Array.from(this._attachedShapes.values());
|
|
23601
|
+
}
|
|
23602
|
+
/**
|
|
23603
|
+
* Get all shapes where this player is currently located
|
|
23604
|
+
*
|
|
23605
|
+
* Returns all shapes (from any player/event) where this player is currently inside.
|
|
23606
|
+
* This is updated automatically when the player enters or exits shapes.
|
|
23607
|
+
*
|
|
23608
|
+
* @returns Array of RpgShape instances where this player is located
|
|
23609
|
+
*
|
|
23610
|
+
* @example
|
|
23611
|
+
* ```ts
|
|
23612
|
+
* // Another player has a detection zone
|
|
23613
|
+
* otherPlayer.attachShape("detection", { radius: 200 });
|
|
23614
|
+
*
|
|
23615
|
+
* // Check if this player is in any shape
|
|
23616
|
+
* const inShapes = player.getInShapes();
|
|
23617
|
+
* if (inShapes.length > 0) {
|
|
23618
|
+
* console.log("Player is being detected!");
|
|
23619
|
+
* }
|
|
23620
|
+
* ```
|
|
23621
|
+
*/
|
|
23622
|
+
getInShapes() {
|
|
23623
|
+
return Array.from(this._inShapes);
|
|
22629
23624
|
}
|
|
22630
23625
|
/**
|
|
22631
23626
|
* Show a temporary component animation on this player
|
|
@@ -22645,29 +23640,102 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22645
23640
|
* color: "red"
|
|
22646
23641
|
* });
|
|
22647
23642
|
*
|
|
22648
|
-
* // Show a heal animation
|
|
22649
|
-
* player.showComponentAnimation("heal", {
|
|
22650
|
-
* amount: 50
|
|
22651
|
-
* });
|
|
23643
|
+
* // Show a heal animation
|
|
23644
|
+
* player.showComponentAnimation("heal", {
|
|
23645
|
+
* amount: 50
|
|
23646
|
+
* });
|
|
23647
|
+
* ```
|
|
23648
|
+
*/
|
|
23649
|
+
showComponentAnimation(id, params = {}) {
|
|
23650
|
+
const map2 = this.getCurrentMap();
|
|
23651
|
+
if (!map2) return;
|
|
23652
|
+
map2.$broadcast({
|
|
23653
|
+
type: "showComponentAnimation",
|
|
23654
|
+
value: {
|
|
23655
|
+
id,
|
|
23656
|
+
params,
|
|
23657
|
+
object: this.id
|
|
23658
|
+
}
|
|
23659
|
+
});
|
|
23660
|
+
}
|
|
23661
|
+
showHit(text) {
|
|
23662
|
+
this.showComponentAnimation("hit", {
|
|
23663
|
+
text,
|
|
23664
|
+
direction: this.direction()
|
|
23665
|
+
});
|
|
23666
|
+
}
|
|
23667
|
+
/**
|
|
23668
|
+
* Play a sound on the client side for this player only
|
|
23669
|
+
*
|
|
23670
|
+
* This method emits an event to play a sound only for this specific player.
|
|
23671
|
+
* The sound must be defined on the client side (in the client module configuration).
|
|
23672
|
+
*
|
|
23673
|
+
* ## Design
|
|
23674
|
+
*
|
|
23675
|
+
* The sound is sent only to this player's client connection, making it ideal
|
|
23676
|
+
* for personal feedback sounds like UI interactions, notifications, or personal
|
|
23677
|
+
* achievements. For map-wide sounds that all players should hear, use `map.playSound()` instead.
|
|
23678
|
+
*
|
|
23679
|
+
* @param soundId - Sound identifier, defined on the client side
|
|
23680
|
+
* @param options - Optional sound configuration
|
|
23681
|
+
* @param options.volume - Volume level (0.0 to 1.0, default: 1.0)
|
|
23682
|
+
* @param options.loop - Whether the sound should loop (default: false)
|
|
23683
|
+
*
|
|
23684
|
+
* @example
|
|
23685
|
+
* ```ts
|
|
23686
|
+
* // Play a sound for this player only (default behavior)
|
|
23687
|
+
* player.playSound("item-pickup");
|
|
23688
|
+
*
|
|
23689
|
+
* // Play a sound with volume and loop
|
|
23690
|
+
* player.playSound("background-music", {
|
|
23691
|
+
* volume: 0.5,
|
|
23692
|
+
* loop: true
|
|
23693
|
+
* });
|
|
23694
|
+
*
|
|
23695
|
+
* // Play a notification sound at low volume
|
|
23696
|
+
* player.playSound("notification", { volume: 0.3 });
|
|
23697
|
+
* ```
|
|
23698
|
+
*/
|
|
23699
|
+
playSound(soundId, options) {
|
|
23700
|
+
const map2 = this.getCurrentMap();
|
|
23701
|
+
if (!map2) return;
|
|
23702
|
+
const data = {
|
|
23703
|
+
soundId
|
|
23704
|
+
};
|
|
23705
|
+
if (options) {
|
|
23706
|
+
if (options.volume !== void 0) {
|
|
23707
|
+
data.volume = Math.max(0, Math.min(1, options.volume));
|
|
23708
|
+
}
|
|
23709
|
+
if (options.loop !== void 0) {
|
|
23710
|
+
data.loop = options.loop;
|
|
23711
|
+
}
|
|
23712
|
+
}
|
|
23713
|
+
this.emit("playSound", data);
|
|
23714
|
+
}
|
|
23715
|
+
/**
|
|
23716
|
+
* Stop a sound that is currently playing for this player
|
|
23717
|
+
*
|
|
23718
|
+
* This method stops a sound that was previously started with `playSound()`.
|
|
23719
|
+
* The sound must be defined on the client side.
|
|
23720
|
+
*
|
|
23721
|
+
* @param soundId - Sound identifier to stop
|
|
23722
|
+
*
|
|
23723
|
+
* @example
|
|
23724
|
+
* ```ts
|
|
23725
|
+
* // Start a looping background music
|
|
23726
|
+
* player.playSound("background-music", { loop: true });
|
|
23727
|
+
*
|
|
23728
|
+
* // Later, stop it
|
|
23729
|
+
* player.stopSound("background-music");
|
|
22652
23730
|
* ```
|
|
22653
23731
|
*/
|
|
22654
|
-
|
|
22655
|
-
const
|
|
22656
|
-
if (!
|
|
22657
|
-
|
|
22658
|
-
|
|
22659
|
-
|
|
22660
|
-
|
|
22661
|
-
params,
|
|
22662
|
-
object: this.id
|
|
22663
|
-
}
|
|
22664
|
-
});
|
|
22665
|
-
}
|
|
22666
|
-
showHit(text) {
|
|
22667
|
-
this.showComponentAnimation("hit", {
|
|
22668
|
-
text,
|
|
22669
|
-
direction: this.direction()
|
|
22670
|
-
});
|
|
23732
|
+
stopSound(soundId) {
|
|
23733
|
+
const map2 = this.getCurrentMap();
|
|
23734
|
+
if (!map2) return;
|
|
23735
|
+
const data = {
|
|
23736
|
+
soundId
|
|
23737
|
+
};
|
|
23738
|
+
this.emit("stopSound", data);
|
|
22671
23739
|
}
|
|
22672
23740
|
/**
|
|
22673
23741
|
* Set the sync schema for the map
|
|
@@ -22696,9 +23764,9 @@ class RpgEvent extends RpgPlayer {
|
|
|
22696
23764
|
return ret;
|
|
22697
23765
|
}
|
|
22698
23766
|
remove() {
|
|
22699
|
-
const
|
|
22700
|
-
if (!
|
|
22701
|
-
|
|
23767
|
+
const map2 = this.getCurrentMap();
|
|
23768
|
+
if (!map2) return;
|
|
23769
|
+
map2.removeEvent(this.id);
|
|
22702
23770
|
}
|
|
22703
23771
|
}
|
|
22704
23772
|
|
|
@@ -26027,12 +27095,126 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
26027
27095
|
this.dataIsReady$ = new BehaviorSubject$1(void 0);
|
|
26028
27096
|
this.globalConfig = {};
|
|
26029
27097
|
this.damageFormulas = {};
|
|
27098
|
+
/** Internal: Map of shapes by name */
|
|
27099
|
+
this._shapes = /* @__PURE__ */ new Map();
|
|
27100
|
+
/** Internal: Map of shape entity UUIDs to RpgShape instances */
|
|
27101
|
+
this._shapeEntities = /* @__PURE__ */ new Map();
|
|
26030
27102
|
this.hooks.callHooks("server-map-onStart", this).subscribe();
|
|
26031
27103
|
this.throttleSync = this.isStandalone ? 0 : 50;
|
|
26032
27104
|
this.throttleStorage = this.isStandalone ? 0 : 1e3;
|
|
26033
27105
|
this.sessionExpiryTime = 1e3 * 60 * 5;
|
|
27106
|
+
this.setupCollisionDetection();
|
|
26034
27107
|
this.loop();
|
|
26035
27108
|
}
|
|
27109
|
+
/**
|
|
27110
|
+
* Setup collision detection between players, events, and shapes
|
|
27111
|
+
*
|
|
27112
|
+
* This method listens to physics collision events and triggers hooks:
|
|
27113
|
+
* - `onPlayerTouch` on events when a player collides with them
|
|
27114
|
+
* - `onInShape` on players and events when they enter a shape
|
|
27115
|
+
* - `onOutShape` on players and events when they exit a shape
|
|
27116
|
+
*
|
|
27117
|
+
* ## Architecture
|
|
27118
|
+
*
|
|
27119
|
+
* Uses the physics engine's collision event system to detect when entities collide.
|
|
27120
|
+
* When a collision is detected:
|
|
27121
|
+
* - Between a player and an event: triggers `onPlayerTouch` on the event
|
|
27122
|
+
* - Between a player/event and a shape: triggers `onInShape`/`onOutShape` hooks
|
|
27123
|
+
*
|
|
27124
|
+
* @example
|
|
27125
|
+
* ```ts
|
|
27126
|
+
* // Event with onPlayerTouch hook
|
|
27127
|
+
* map.createDynamicEvent({
|
|
27128
|
+
* x: 100,
|
|
27129
|
+
* y: 200,
|
|
27130
|
+
* event: {
|
|
27131
|
+
* onPlayerTouch(player) {
|
|
27132
|
+
* console.log(`Player ${player.id} touched this event!`);
|
|
27133
|
+
* }
|
|
27134
|
+
* }
|
|
27135
|
+
* });
|
|
27136
|
+
*
|
|
27137
|
+
* // Player with onInShape hook
|
|
27138
|
+
* const player: RpgPlayerHooks = {
|
|
27139
|
+
* onInShape(player: RpgPlayer, shape: RpgShape) {
|
|
27140
|
+
* console.log('in', player.name, shape.name);
|
|
27141
|
+
* },
|
|
27142
|
+
* onOutShape(player: RpgPlayer, shape: RpgShape) {
|
|
27143
|
+
* console.log('out', player.name, shape.name);
|
|
27144
|
+
* }
|
|
27145
|
+
* };
|
|
27146
|
+
* ```
|
|
27147
|
+
*/
|
|
27148
|
+
setupCollisionDetection() {
|
|
27149
|
+
const activeCollisions = /* @__PURE__ */ new Set();
|
|
27150
|
+
const activeShapeCollisions = /* @__PURE__ */ new Set();
|
|
27151
|
+
this.physic.getEvents().onCollisionEnter((collision) => {
|
|
27152
|
+
const entityA = collision.entityA;
|
|
27153
|
+
const entityB = collision.entityB;
|
|
27154
|
+
const collisionKey = entityA.uuid < entityB.uuid ? `${entityA.uuid}-${entityB.uuid}` : `${entityB.uuid}-${entityA.uuid}`;
|
|
27155
|
+
if (activeCollisions.has(collisionKey)) {
|
|
27156
|
+
return;
|
|
27157
|
+
}
|
|
27158
|
+
const shapeA = this._shapeEntities.get(entityA.uuid);
|
|
27159
|
+
const shapeB = this._shapeEntities.get(entityB.uuid);
|
|
27160
|
+
if (shapeA || shapeB) {
|
|
27161
|
+
const shape = shapeA || shapeB;
|
|
27162
|
+
const otherEntity = shapeA ? entityB : entityA;
|
|
27163
|
+
if (shape) {
|
|
27164
|
+
const shapeKey = `${otherEntity.uuid}-${shape.name}`;
|
|
27165
|
+
if (!activeShapeCollisions.has(shapeKey)) {
|
|
27166
|
+
activeShapeCollisions.add(shapeKey);
|
|
27167
|
+
const player2 = this.getPlayer(otherEntity.uuid);
|
|
27168
|
+
const event2 = this.getEvent(otherEntity.uuid);
|
|
27169
|
+
if (player2) {
|
|
27170
|
+
player2.execMethod("onInShape", [player2, shape]);
|
|
27171
|
+
}
|
|
27172
|
+
if (event2) {
|
|
27173
|
+
event2.execMethod("onInShape", [shape, player2 || event2]);
|
|
27174
|
+
}
|
|
27175
|
+
}
|
|
27176
|
+
}
|
|
27177
|
+
return;
|
|
27178
|
+
}
|
|
27179
|
+
const player = this.getPlayer(entityA.uuid) || this.getPlayer(entityB.uuid);
|
|
27180
|
+
if (!player) {
|
|
27181
|
+
return;
|
|
27182
|
+
}
|
|
27183
|
+
const eventId = player.id === entityA.uuid ? entityB.uuid : entityA.uuid;
|
|
27184
|
+
const event = this.getEvent(eventId);
|
|
27185
|
+
if (event) {
|
|
27186
|
+
activeCollisions.add(collisionKey);
|
|
27187
|
+
event.execMethod("onPlayerTouch", [player]);
|
|
27188
|
+
}
|
|
27189
|
+
});
|
|
27190
|
+
this.physic.getEvents().onCollisionExit((collision) => {
|
|
27191
|
+
const entityA = collision.entityA;
|
|
27192
|
+
const entityB = collision.entityB;
|
|
27193
|
+
const collisionKey = entityA.uuid < entityB.uuid ? `${entityA.uuid}-${entityB.uuid}` : `${entityB.uuid}-${entityA.uuid}`;
|
|
27194
|
+
const shapeA = this._shapeEntities.get(entityA.uuid);
|
|
27195
|
+
const shapeB = this._shapeEntities.get(entityB.uuid);
|
|
27196
|
+
if (shapeA || shapeB) {
|
|
27197
|
+
const shape = shapeA || shapeB;
|
|
27198
|
+
const otherEntity = shapeA ? entityB : entityA;
|
|
27199
|
+
if (shape) {
|
|
27200
|
+
const shapeKey = `${otherEntity.uuid}-${shape.name}`;
|
|
27201
|
+
if (activeShapeCollisions.has(shapeKey)) {
|
|
27202
|
+
activeShapeCollisions.delete(shapeKey);
|
|
27203
|
+
const player = this.getPlayer(otherEntity.uuid);
|
|
27204
|
+
const event = this.getEvent(otherEntity.uuid);
|
|
27205
|
+
if (player) {
|
|
27206
|
+
player.execMethod("onOutShape", [player, shape]);
|
|
27207
|
+
}
|
|
27208
|
+
if (event) {
|
|
27209
|
+
event.execMethod("onOutShape", [shape, player || event]);
|
|
27210
|
+
}
|
|
27211
|
+
}
|
|
27212
|
+
}
|
|
27213
|
+
return;
|
|
27214
|
+
}
|
|
27215
|
+
activeCollisions.delete(collisionKey);
|
|
27216
|
+
});
|
|
27217
|
+
}
|
|
26036
27218
|
// autoload by @signe/room
|
|
26037
27219
|
interceptorPacket(player, packet, conn) {
|
|
26038
27220
|
let obj = {};
|
|
@@ -26069,7 +27251,6 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
26069
27251
|
player._onInit();
|
|
26070
27252
|
this.dataIsReady$.pipe(
|
|
26071
27253
|
finalize$1(() => {
|
|
26072
|
-
player.applyFrames();
|
|
26073
27254
|
this.hooks.callHooks("server-player-onJoinMap", player, this).subscribe();
|
|
26074
27255
|
})
|
|
26075
27256
|
).subscribe();
|
|
@@ -26189,8 +27370,16 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
26189
27370
|
* This method processes all pending inputs for a player while performing
|
|
26190
27371
|
* anti-cheat validation to prevent time manipulation and frame skipping.
|
|
26191
27372
|
* It validates the time deltas between inputs and ensures they are within
|
|
26192
|
-
* acceptable ranges.
|
|
26193
|
-
*
|
|
27373
|
+
* acceptable ranges.
|
|
27374
|
+
*
|
|
27375
|
+
* ## Architecture
|
|
27376
|
+
*
|
|
27377
|
+
* **Important**: This method only updates entity velocities - it does NOT step
|
|
27378
|
+
* the physics engine. Physics simulation is handled centrally by the game loop
|
|
27379
|
+
* (`tick$` -> `runFixedTicks`). This ensures:
|
|
27380
|
+
* - Consistent physics timing (60fps fixed timestep)
|
|
27381
|
+
* - No double-stepping when multiple inputs are processed
|
|
27382
|
+
* - Deterministic physics regardless of input frequency
|
|
26194
27383
|
*
|
|
26195
27384
|
* @param playerId - The ID of the player to process inputs for
|
|
26196
27385
|
* @param controls - Optional anti-cheat configuration
|
|
@@ -26272,7 +27461,6 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
26272
27461
|
lastProcessedFrame = input.frame;
|
|
26273
27462
|
}
|
|
26274
27463
|
if (hasProcessedInputs) {
|
|
26275
|
-
this.forceSingleTick();
|
|
26276
27464
|
player.lastProcessedInputTs = lastProcessedTime;
|
|
26277
27465
|
} else {
|
|
26278
27466
|
const idleTimeout = Math.max(config.minTimeBetweenInputs * 4, 50);
|
|
@@ -26282,7 +27470,6 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
26282
27470
|
player.lastProcessedInputTs = 0;
|
|
26283
27471
|
}
|
|
26284
27472
|
}
|
|
26285
|
-
player.applyFrames();
|
|
26286
27473
|
return {
|
|
26287
27474
|
player,
|
|
26288
27475
|
inputs: processedInputs
|
|
@@ -26419,7 +27606,6 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
26419
27606
|
eventInstance.context = context$1;
|
|
26420
27607
|
eventInstance.x.set(x);
|
|
26421
27608
|
eventInstance.y.set(y);
|
|
26422
|
-
eventInstance.applyFrames();
|
|
26423
27609
|
if (event.name) eventInstance.name.set(event.name);
|
|
26424
27610
|
this.events()[id] = eventInstance;
|
|
26425
27611
|
await eventInstance.execMethod("onInit");
|
|
@@ -26544,6 +27730,277 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
26544
27730
|
}, holder);
|
|
26545
27731
|
}
|
|
26546
27732
|
}
|
|
27733
|
+
/**
|
|
27734
|
+
* Create a shape dynamically on the map
|
|
27735
|
+
*
|
|
27736
|
+
* This method creates a static hitbox on the map that can be used for
|
|
27737
|
+
* collision detection, area triggers, or visual boundaries. The shape is
|
|
27738
|
+
* backed by the physics engine's static entity system for accurate collision detection.
|
|
27739
|
+
*
|
|
27740
|
+
* ## Architecture
|
|
27741
|
+
*
|
|
27742
|
+
* Creates a static entity (hitbox) in the physics engine at the specified position and size.
|
|
27743
|
+
* The shape is stored internally and can be retrieved by name. When players or events
|
|
27744
|
+
* collide with this hitbox, the `onInShape` and `onOutShape` hooks are automatically
|
|
27745
|
+
* triggered on both the player and the event.
|
|
27746
|
+
*
|
|
27747
|
+
* @param obj - Shape configuration object
|
|
27748
|
+
* @param obj.x - X position of the shape (top-left corner) (required)
|
|
27749
|
+
* @param obj.y - Y position of the shape (top-left corner) (required)
|
|
27750
|
+
* @param obj.width - Width of the shape in pixels (required)
|
|
27751
|
+
* @param obj.height - Height of the shape in pixels (required)
|
|
27752
|
+
* @param obj.name - Name of the shape (optional, auto-generated if not provided)
|
|
27753
|
+
* @param obj.z - Z position/depth for rendering (optional)
|
|
27754
|
+
* @param obj.color - Color in hexadecimal format, shared with client (optional)
|
|
27755
|
+
* @param obj.collision - Whether the shape has collision (optional)
|
|
27756
|
+
* @param obj.properties - Additional custom properties (optional)
|
|
27757
|
+
* @returns The created RpgShape instance
|
|
27758
|
+
*
|
|
27759
|
+
* @example
|
|
27760
|
+
* ```ts
|
|
27761
|
+
* // Create a simple rectangular shape
|
|
27762
|
+
* const shape = map.createShape({
|
|
27763
|
+
* x: 100,
|
|
27764
|
+
* y: 200,
|
|
27765
|
+
* width: 50,
|
|
27766
|
+
* height: 50,
|
|
27767
|
+
* name: "spawn-zone"
|
|
27768
|
+
* });
|
|
27769
|
+
*
|
|
27770
|
+
* // Create a shape with visual properties
|
|
27771
|
+
* const triggerZone = map.createShape({
|
|
27772
|
+
* x: 300,
|
|
27773
|
+
* y: 400,
|
|
27774
|
+
* width: 100,
|
|
27775
|
+
* height: 100,
|
|
27776
|
+
* name: "treasure-area",
|
|
27777
|
+
* color: "#FFD700",
|
|
27778
|
+
* z: 1,
|
|
27779
|
+
* collision: false,
|
|
27780
|
+
* properties: {
|
|
27781
|
+
* type: "treasure",
|
|
27782
|
+
* value: 100
|
|
27783
|
+
* }
|
|
27784
|
+
* });
|
|
27785
|
+
*
|
|
27786
|
+
* // Player hooks will be triggered automatically
|
|
27787
|
+
* const player: RpgPlayerHooks = {
|
|
27788
|
+
* onInShape(player: RpgPlayer, shape: RpgShape) {
|
|
27789
|
+
* console.log('in', player.name, shape.name);
|
|
27790
|
+
* },
|
|
27791
|
+
* onOutShape(player: RpgPlayer, shape: RpgShape) {
|
|
27792
|
+
* console.log('out', player.name, shape.name);
|
|
27793
|
+
* }
|
|
27794
|
+
* };
|
|
27795
|
+
* ```
|
|
27796
|
+
*/
|
|
27797
|
+
createShape(obj) {
|
|
27798
|
+
const { x, y, width, height } = obj;
|
|
27799
|
+
if (typeof x !== "number" || typeof y !== "number") {
|
|
27800
|
+
throw new Error("Shape x and y must be numbers");
|
|
27801
|
+
}
|
|
27802
|
+
if (typeof width !== "number" || width <= 0) {
|
|
27803
|
+
throw new Error("Shape width must be a positive number");
|
|
27804
|
+
}
|
|
27805
|
+
if (typeof height !== "number" || height <= 0) {
|
|
27806
|
+
throw new Error("Shape height must be a positive number");
|
|
27807
|
+
}
|
|
27808
|
+
const name = obj.name || generateShortUUID$2();
|
|
27809
|
+
if (this._shapes.has(name)) {
|
|
27810
|
+
throw new Error(`Shape with name "${name}" already exists`);
|
|
27811
|
+
}
|
|
27812
|
+
const centerX = x + width / 2;
|
|
27813
|
+
const centerY = y + height / 2;
|
|
27814
|
+
const entityId = `shape-${name}`;
|
|
27815
|
+
const entity = this.physic.createEntity({
|
|
27816
|
+
uuid: entityId,
|
|
27817
|
+
position: { x: centerX, y: centerY },
|
|
27818
|
+
width,
|
|
27819
|
+
height,
|
|
27820
|
+
mass: Infinity,
|
|
27821
|
+
// Static entity
|
|
27822
|
+
state: EntityState.Static,
|
|
27823
|
+
restitution: 0
|
|
27824
|
+
// No bounce
|
|
27825
|
+
});
|
|
27826
|
+
entity.freeze();
|
|
27827
|
+
const properties = {
|
|
27828
|
+
...obj.properties || {}
|
|
27829
|
+
};
|
|
27830
|
+
if (obj.z !== void 0) properties.z = obj.z;
|
|
27831
|
+
if (obj.color !== void 0) properties.color = obj.color;
|
|
27832
|
+
if (obj.collision !== void 0) properties.collision = obj.collision;
|
|
27833
|
+
const shape = new RpgShape({
|
|
27834
|
+
name,
|
|
27835
|
+
positioning: "default",
|
|
27836
|
+
width,
|
|
27837
|
+
height,
|
|
27838
|
+
x: centerX,
|
|
27839
|
+
y: centerY,
|
|
27840
|
+
properties,
|
|
27841
|
+
playerOwner: void 0,
|
|
27842
|
+
// Static shapes are not attached to players
|
|
27843
|
+
physicZoneId: entityId,
|
|
27844
|
+
// Store entity UUID for reference
|
|
27845
|
+
map: this
|
|
27846
|
+
});
|
|
27847
|
+
this._shapes.set(name, shape);
|
|
27848
|
+
this._shapeEntities.set(entityId, shape);
|
|
27849
|
+
return shape;
|
|
27850
|
+
}
|
|
27851
|
+
/**
|
|
27852
|
+
* Delete a shape from the map
|
|
27853
|
+
*
|
|
27854
|
+
* Removes a shape by its name and cleans up the associated static hitbox entity.
|
|
27855
|
+
* If the shape doesn't exist, the method does nothing.
|
|
27856
|
+
*
|
|
27857
|
+
* @param name - Name of the shape to remove
|
|
27858
|
+
* @returns void
|
|
27859
|
+
*
|
|
27860
|
+
* @example
|
|
27861
|
+
* ```ts
|
|
27862
|
+
* // Create and then remove a shape
|
|
27863
|
+
* const shape = map.createShape({
|
|
27864
|
+
* x: 100,
|
|
27865
|
+
* y: 200,
|
|
27866
|
+
* width: 50,
|
|
27867
|
+
* height: 50,
|
|
27868
|
+
* name: "temp-zone"
|
|
27869
|
+
* });
|
|
27870
|
+
*
|
|
27871
|
+
* // Later, remove it
|
|
27872
|
+
* map.removeShape("temp-zone");
|
|
27873
|
+
* ```
|
|
27874
|
+
*/
|
|
27875
|
+
removeShape(name) {
|
|
27876
|
+
const shape = this._shapes.get(name);
|
|
27877
|
+
if (!shape) {
|
|
27878
|
+
return;
|
|
27879
|
+
}
|
|
27880
|
+
const entityId = shape._physicZoneId;
|
|
27881
|
+
const entity = this.physic.getEntityByUUID(entityId);
|
|
27882
|
+
if (entity) {
|
|
27883
|
+
this.physic.removeEntity(entity);
|
|
27884
|
+
}
|
|
27885
|
+
this._shapes.delete(name);
|
|
27886
|
+
this._shapeEntities.delete(entityId);
|
|
27887
|
+
}
|
|
27888
|
+
/**
|
|
27889
|
+
* Get all shapes on the map
|
|
27890
|
+
*
|
|
27891
|
+
* Returns an array of all shapes that have been created on this map,
|
|
27892
|
+
* regardless of whether they are static shapes or player-attached shapes.
|
|
27893
|
+
*
|
|
27894
|
+
* @returns Array of RpgShape instances
|
|
27895
|
+
*
|
|
27896
|
+
* @example
|
|
27897
|
+
* ```ts
|
|
27898
|
+
* // Create multiple shapes
|
|
27899
|
+
* map.createShape({ x: 0, y: 0, width: 50, height: 50, name: "zone1" });
|
|
27900
|
+
* map.createShape({ x: 100, y: 100, width: 50, height: 50, name: "zone2" });
|
|
27901
|
+
*
|
|
27902
|
+
* // Get all shapes
|
|
27903
|
+
* const allShapes = map.getShapes();
|
|
27904
|
+
* console.log(allShapes.length); // 2
|
|
27905
|
+
* ```
|
|
27906
|
+
*/
|
|
27907
|
+
getShapes() {
|
|
27908
|
+
return Array.from(this._shapes.values());
|
|
27909
|
+
}
|
|
27910
|
+
/**
|
|
27911
|
+
* Get a shape by its name
|
|
27912
|
+
*
|
|
27913
|
+
* Returns a shape with the specified name, or undefined if no shape
|
|
27914
|
+
* with that name exists on the map.
|
|
27915
|
+
*
|
|
27916
|
+
* @param name - Name of the shape to retrieve
|
|
27917
|
+
* @returns The RpgShape instance, or undefined if not found
|
|
27918
|
+
*
|
|
27919
|
+
* @example
|
|
27920
|
+
* ```ts
|
|
27921
|
+
* // Create a shape with a specific name
|
|
27922
|
+
* map.createShape({
|
|
27923
|
+
* x: 100,
|
|
27924
|
+
* y: 200,
|
|
27925
|
+
* width: 50,
|
|
27926
|
+
* height: 50,
|
|
27927
|
+
* name: "spawn-point"
|
|
27928
|
+
* });
|
|
27929
|
+
*
|
|
27930
|
+
* // Retrieve it later
|
|
27931
|
+
* const spawnZone = map.getShape("spawn-point");
|
|
27932
|
+
* if (spawnZone) {
|
|
27933
|
+
* console.log(`Spawn zone at (${spawnZone.x}, ${spawnZone.y})`);
|
|
27934
|
+
* }
|
|
27935
|
+
* ```
|
|
27936
|
+
*/
|
|
27937
|
+
getShape(name) {
|
|
27938
|
+
return this._shapes.get(name);
|
|
27939
|
+
}
|
|
27940
|
+
/**
|
|
27941
|
+
* Play a sound for all players on the map
|
|
27942
|
+
*
|
|
27943
|
+
* This method plays a sound for all players currently on the map by iterating
|
|
27944
|
+
* over each player and calling `player.playSound()`. The sound must be defined
|
|
27945
|
+
* on the client side (in the client module configuration).
|
|
27946
|
+
* This is ideal for environmental sounds, battle music, or map-wide events that
|
|
27947
|
+
* all players should hear simultaneously.
|
|
27948
|
+
*
|
|
27949
|
+
* ## Design
|
|
27950
|
+
*
|
|
27951
|
+
* Iterates over all players on the map and calls `player.playSound()` for each one.
|
|
27952
|
+
* This avoids code duplication and reuses the existing player sound logic.
|
|
27953
|
+
* For player-specific sounds, use `player.playSound()` directly.
|
|
27954
|
+
*
|
|
27955
|
+
* @param soundId - Sound identifier, defined on the client side
|
|
27956
|
+
* @param options - Optional sound configuration
|
|
27957
|
+
* @param options.volume - Volume level (0.0 to 1.0, default: 1.0)
|
|
27958
|
+
* @param options.loop - Whether the sound should loop (default: false)
|
|
27959
|
+
*
|
|
27960
|
+
* @example
|
|
27961
|
+
* ```ts
|
|
27962
|
+
* // Play a sound for all players on the map
|
|
27963
|
+
* map.playSound("explosion");
|
|
27964
|
+
*
|
|
27965
|
+
* // Play background music for everyone with volume and loop
|
|
27966
|
+
* map.playSound("battle-theme", {
|
|
27967
|
+
* volume: 0.7,
|
|
27968
|
+
* loop: true
|
|
27969
|
+
* });
|
|
27970
|
+
*
|
|
27971
|
+
* // Play a door opening sound at low volume
|
|
27972
|
+
* map.playSound("door-open", { volume: 0.4 });
|
|
27973
|
+
* ```
|
|
27974
|
+
*/
|
|
27975
|
+
playSound(soundId, options) {
|
|
27976
|
+
const players = this.getPlayers();
|
|
27977
|
+
players.forEach((player) => {
|
|
27978
|
+
player.playSound(soundId, options);
|
|
27979
|
+
});
|
|
27980
|
+
}
|
|
27981
|
+
/**
|
|
27982
|
+
* Stop a sound for all players on the map
|
|
27983
|
+
*
|
|
27984
|
+
* This method stops a sound that was previously started with `map.playSound()`
|
|
27985
|
+
* for all players on the map by iterating over each player and calling `player.stopSound()`.
|
|
27986
|
+
*
|
|
27987
|
+
* @param soundId - Sound identifier to stop
|
|
27988
|
+
*
|
|
27989
|
+
* @example
|
|
27990
|
+
* ```ts
|
|
27991
|
+
* // Start background music for everyone
|
|
27992
|
+
* map.playSound("battle-theme", { loop: true });
|
|
27993
|
+
*
|
|
27994
|
+
* // Later, stop it for everyone
|
|
27995
|
+
* map.stopSound("battle-theme");
|
|
27996
|
+
* ```
|
|
27997
|
+
*/
|
|
27998
|
+
stopSound(soundId) {
|
|
27999
|
+
const players = this.getPlayers();
|
|
28000
|
+
players.forEach((player) => {
|
|
28001
|
+
player.stopSound(soundId);
|
|
28002
|
+
});
|
|
28003
|
+
}
|
|
26547
28004
|
};
|
|
26548
28005
|
__decorateClass$1([
|
|
26549
28006
|
users$1(RpgPlayer)
|
|
@@ -26646,6 +28103,234 @@ function createServer(options) {
|
|
|
26646
28103
|
};
|
|
26647
28104
|
}
|
|
26648
28105
|
|
|
28106
|
+
const Components = {
|
|
28107
|
+
/**
|
|
28108
|
+
* Create a text component
|
|
28109
|
+
*
|
|
28110
|
+
* Creates a text component that displays text with optional styling.
|
|
28111
|
+
* Supports template strings with placeholders like {name}, {hp}, etc.
|
|
28112
|
+
* that are replaced with actual player property values.
|
|
28113
|
+
*
|
|
28114
|
+
* ## Design
|
|
28115
|
+
*
|
|
28116
|
+
* Text components use template strings to allow dynamic content without
|
|
28117
|
+
* resending the entire component structure when values change. Only the
|
|
28118
|
+
* property values are synchronized, reducing bandwidth usage.
|
|
28119
|
+
*
|
|
28120
|
+
* @param text - Text to display, can include placeholders like {name}, {hp}
|
|
28121
|
+
* @param options - Text styling options
|
|
28122
|
+
* @returns Component definition for text
|
|
28123
|
+
*
|
|
28124
|
+
* @example
|
|
28125
|
+
* ```ts
|
|
28126
|
+
* // Simple text
|
|
28127
|
+
* Components.text('Player Name');
|
|
28128
|
+
*
|
|
28129
|
+
* // Text with placeholder
|
|
28130
|
+
* Components.text('{name}');
|
|
28131
|
+
*
|
|
28132
|
+
* // Text with styling
|
|
28133
|
+
* Components.text('{name}', {
|
|
28134
|
+
* fill: '#000000',
|
|
28135
|
+
* fontSize: 20
|
|
28136
|
+
* });
|
|
28137
|
+
* ```
|
|
28138
|
+
*/
|
|
28139
|
+
text(value, style) {
|
|
28140
|
+
return {
|
|
28141
|
+
type: "text",
|
|
28142
|
+
value,
|
|
28143
|
+
style
|
|
28144
|
+
};
|
|
28145
|
+
},
|
|
28146
|
+
/**
|
|
28147
|
+
* Create an HP bar component
|
|
28148
|
+
*
|
|
28149
|
+
* Creates a health point bar that automatically displays the player's
|
|
28150
|
+
* current HP relative to their maximum HP. The bar updates automatically
|
|
28151
|
+
* as HP changes.
|
|
28152
|
+
*
|
|
28153
|
+
* ## Design
|
|
28154
|
+
*
|
|
28155
|
+
* HP bars read from the player's hp and param.maxHp properties. The
|
|
28156
|
+
* bar can optionally display text above it showing current, max, or
|
|
28157
|
+
* percentage values.
|
|
28158
|
+
*
|
|
28159
|
+
* @param options - Bar styling options
|
|
28160
|
+
* @param text - Optional text to display above the bar. Can use placeholders:
|
|
28161
|
+
* - {$current} - Current HP value
|
|
28162
|
+
* - {$max} - Maximum HP value
|
|
28163
|
+
* - {$percent} - Percentage value
|
|
28164
|
+
* Set to null to hide text
|
|
28165
|
+
* @returns Component definition for HP bar
|
|
28166
|
+
*
|
|
28167
|
+
* @example
|
|
28168
|
+
* ```ts
|
|
28169
|
+
* // Simple HP bar
|
|
28170
|
+
* Components.hpBar();
|
|
28171
|
+
*
|
|
28172
|
+
* // HP bar with percentage text
|
|
28173
|
+
* Components.hpBar({}, '{$percent}%');
|
|
28174
|
+
*
|
|
28175
|
+
* // HP bar with custom styling
|
|
28176
|
+
* Components.hpBar({
|
|
28177
|
+
* fillColor: '#ff0000',
|
|
28178
|
+
* height: 8
|
|
28179
|
+
* });
|
|
28180
|
+
* ```
|
|
28181
|
+
*/
|
|
28182
|
+
hpBar(style, text) {
|
|
28183
|
+
return {
|
|
28184
|
+
type: "hpBar",
|
|
28185
|
+
style,
|
|
28186
|
+
text: text ?? void 0
|
|
28187
|
+
};
|
|
28188
|
+
},
|
|
28189
|
+
/**
|
|
28190
|
+
* Create an SP bar component
|
|
28191
|
+
*
|
|
28192
|
+
* Creates a skill point bar that automatically displays the player's
|
|
28193
|
+
* current SP relative to their maximum SP. The bar updates automatically
|
|
28194
|
+
* as SP changes.
|
|
28195
|
+
*
|
|
28196
|
+
* @param style - Bar styling options
|
|
28197
|
+
* @param text - Optional text to display above the bar. Can use placeholders:
|
|
28198
|
+
* - {$current} - Current SP value
|
|
28199
|
+
* - {$max} - Maximum SP value
|
|
28200
|
+
* - {$percent} - Percentage value
|
|
28201
|
+
* Set to null to hide text
|
|
28202
|
+
* @returns Component definition for SP bar
|
|
28203
|
+
*
|
|
28204
|
+
* @example
|
|
28205
|
+
* ```ts
|
|
28206
|
+
* // Simple SP bar
|
|
28207
|
+
* Components.spBar();
|
|
28208
|
+
*
|
|
28209
|
+
* // SP bar with text
|
|
28210
|
+
* Components.spBar({}, 'SP: {$current}/{$max}');
|
|
28211
|
+
* ```
|
|
28212
|
+
*/
|
|
28213
|
+
spBar(style, text) {
|
|
28214
|
+
return {
|
|
28215
|
+
type: "spBar",
|
|
28216
|
+
style,
|
|
28217
|
+
text: text ?? void 0
|
|
28218
|
+
};
|
|
28219
|
+
},
|
|
28220
|
+
/**
|
|
28221
|
+
* Create a custom bar component
|
|
28222
|
+
*
|
|
28223
|
+
* Creates a bar that displays a custom property value relative to a maximum.
|
|
28224
|
+
* Useful for displaying custom resources like wood, mana, energy, etc.
|
|
28225
|
+
*
|
|
28226
|
+
* @param current - Property path for current value (e.g., 'wood', 'mana')
|
|
28227
|
+
* @param max - Property path for maximum value (e.g., 'param.maxWood', 'param.maxMana')
|
|
28228
|
+
* @param style - Bar styling options
|
|
28229
|
+
* @param text - Optional text to display above the bar. Can use placeholders:
|
|
28230
|
+
* - {$current} - Current value
|
|
28231
|
+
* - {$max} - Maximum value
|
|
28232
|
+
* - {$percent} - Percentage value
|
|
28233
|
+
* Set to null to hide text
|
|
28234
|
+
* @returns Component definition for custom bar
|
|
28235
|
+
*
|
|
28236
|
+
* @example
|
|
28237
|
+
* ```ts
|
|
28238
|
+
* // Bar for custom property
|
|
28239
|
+
* Components.bar('wood', 'param.maxWood');
|
|
28240
|
+
*
|
|
28241
|
+
* // Bar with text
|
|
28242
|
+
* Components.bar('mana', 'param.maxMana', {}, 'Mana: {$current}/{$max}');
|
|
28243
|
+
* ```
|
|
28244
|
+
*/
|
|
28245
|
+
bar(current, max, style, text) {
|
|
28246
|
+
return {
|
|
28247
|
+
type: "bar",
|
|
28248
|
+
current,
|
|
28249
|
+
max,
|
|
28250
|
+
style,
|
|
28251
|
+
text: text ?? void 0
|
|
28252
|
+
};
|
|
28253
|
+
},
|
|
28254
|
+
/**
|
|
28255
|
+
* Create a shape component
|
|
28256
|
+
*
|
|
28257
|
+
* Creates a geometric shape that can be displayed above or below the player.
|
|
28258
|
+
* Useful for visual indicators, backgrounds, or decorative elements.
|
|
28259
|
+
*
|
|
28260
|
+
* @param value - Shape configuration options
|
|
28261
|
+
* @returns Component definition for shape
|
|
28262
|
+
*
|
|
28263
|
+
* @example
|
|
28264
|
+
* ```ts
|
|
28265
|
+
* // Circle shape
|
|
28266
|
+
* Components.shape({
|
|
28267
|
+
* fill: '#ffffff',
|
|
28268
|
+
* type: 'circle',
|
|
28269
|
+
* radius: 10
|
|
28270
|
+
* });
|
|
28271
|
+
*
|
|
28272
|
+
* // Rectangle shape
|
|
28273
|
+
* Components.shape({
|
|
28274
|
+
* fill: '#ff0000',
|
|
28275
|
+
* type: 'rectangle',
|
|
28276
|
+
* width: 32,
|
|
28277
|
+
* height: 32
|
|
28278
|
+
* });
|
|
28279
|
+
*
|
|
28280
|
+
* // Using parameters
|
|
28281
|
+
* Components.shape({
|
|
28282
|
+
* fill: '#ffffff',
|
|
28283
|
+
* type: 'circle',
|
|
28284
|
+
* radius: 'hp' // radius will be the same as hp value
|
|
28285
|
+
* });
|
|
28286
|
+
* ```
|
|
28287
|
+
*/
|
|
28288
|
+
shape(value) {
|
|
28289
|
+
return {
|
|
28290
|
+
type: "shape",
|
|
28291
|
+
value
|
|
28292
|
+
};
|
|
28293
|
+
},
|
|
28294
|
+
/**
|
|
28295
|
+
* Create an image component
|
|
28296
|
+
*
|
|
28297
|
+
* Displays an image from a URL or spritesheet identifier.
|
|
28298
|
+
*
|
|
28299
|
+
* @param value - Image source URL or spritesheet identifier
|
|
28300
|
+
* @returns Component definition for image
|
|
28301
|
+
*
|
|
28302
|
+
* @example
|
|
28303
|
+
* ```ts
|
|
28304
|
+
* Components.image('mygraphic.png');
|
|
28305
|
+
* ```
|
|
28306
|
+
*/
|
|
28307
|
+
image(value) {
|
|
28308
|
+
return {
|
|
28309
|
+
type: "image",
|
|
28310
|
+
value
|
|
28311
|
+
};
|
|
28312
|
+
},
|
|
28313
|
+
/**
|
|
28314
|
+
* Create a tile component
|
|
28315
|
+
*
|
|
28316
|
+
* Displays a tile from a tileset by ID.
|
|
28317
|
+
*
|
|
28318
|
+
* @param value - Tile ID in the tileset
|
|
28319
|
+
* @returns Component definition for tile
|
|
28320
|
+
*
|
|
28321
|
+
* @example
|
|
28322
|
+
* ```ts
|
|
28323
|
+
* Components.tile(3); // Use tile #3
|
|
28324
|
+
* ```
|
|
28325
|
+
*/
|
|
28326
|
+
tile(value) {
|
|
28327
|
+
return {
|
|
28328
|
+
type: "tile",
|
|
28329
|
+
value
|
|
28330
|
+
};
|
|
28331
|
+
}
|
|
28332
|
+
};
|
|
28333
|
+
|
|
26649
28334
|
function provideServerModules(modules) {
|
|
26650
28335
|
return provideModules(modules, "server", (modules2, context) => {
|
|
26651
28336
|
const mainModuleServer = findModules(context, "Server");
|
|
@@ -26696,5 +28381,5 @@ function provideServerModules(modules) {
|
|
|
26696
28381
|
});
|
|
26697
28382
|
}
|
|
26698
28383
|
|
|
26699
|
-
export { AGI, AGI_CURVE, ATK, ArraySubject$1 as ArraySubject, COEFFICIENT_ELEMENTS, DAMAGE_CRITICAL, DAMAGE_GUARD, DAMAGE_PHYSIC, DAMAGE_SKILL, DEX, DEX_CURVE, DialogGui, DialogPosition, Frequency, Gui, INT, INT_CURVE, MAXHP, MAXHP_CURVE, MAXSP, MAXSP_CURVE, MenuGui, Move, NotificationGui, ObjectSubject$1 as ObjectSubject, PDEF, RpgEvent, RpgMap, RpgPlayer, RpgServerEngine, SDEF, STR, STR_CURVE, ShopGui, Speed, WithMoveManager, clearInject, computed$1 as computed, context, createServer, effect$1 as effect, inject, isArraySubject$1 as isArraySubject, isComputed$1 as isComputed, isObjectSubject$1 as isObjectSubject, isSignal$1 as isSignal, provideServerModules, setInject, signal$1 as signal, untracked$1 as untracked };
|
|
28384
|
+
export { AGI, AGI_CURVE, ATK, ArraySubject$1 as ArraySubject, COEFFICIENT_ELEMENTS, Components, DAMAGE_CRITICAL, DAMAGE_GUARD, DAMAGE_PHYSIC, DAMAGE_SKILL, DEX, DEX_CURVE, DialogGui, DialogPosition, Frequency, Gui, INT, INT_CURVE, MAXHP, MAXHP_CURVE, MAXSP, MAXSP_CURVE, MenuGui, Move, NotificationGui, ObjectSubject$1 as ObjectSubject, PDEF, RpgEvent, RpgMap, RpgPlayer, RpgServerEngine, RpgShape, SDEF, STR, STR_CURVE, ShopGui, Speed, WithMoveManager, clearInject, computed$1 as computed, context, createServer, effect$1 as effect, inject, isArraySubject$1 as isArraySubject, isComputed$1 as isComputed, isObjectSubject$1 as isObjectSubject, isSignal$1 as isSignal, provideServerModules, setInject, signal$1 as signal, untracked$1 as untracked };
|
|
26700
28385
|
//# sourceMappingURL=index.js.map
|