@dcl/ecs 7.26.1-31715266070.commit-0ddb8e7 → 7.26.1-32157237851.commit-e712ef7
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/components/generated/pb/decentraland/sdk/components/avatar_shape.gen.d.ts +0 -8
- package/dist/components/generated/pb/decentraland/sdk/components/avatar_shape.gen.js +0 -9
- package/dist/engine/entity.js +31 -4
- package/dist/engine/index.js +22 -3
- package/dist/engine/types.d.ts +8 -1
- package/dist/systems/triggerArea.js +2 -1
- package/dist-cjs/components/generated/pb/decentraland/sdk/components/avatar_shape.gen.d.ts +0 -8
- package/dist-cjs/components/generated/pb/decentraland/sdk/components/avatar_shape.gen.js +1 -10
- package/dist-cjs/engine/entity.js +31 -4
- package/dist-cjs/engine/index.js +21 -2
- package/dist-cjs/engine/types.d.ts +8 -1
- package/dist-cjs/systems/triggerArea.js +2 -1
- package/package.json +2 -2
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import _m0 from "protobufjs/minimal";
|
|
2
2
|
import { Color3 } from "../../common/colors.gen";
|
|
3
|
-
/** Mask for which bones an animation applies to. */
|
|
4
|
-
/**
|
|
5
|
-
* @public
|
|
6
|
-
*/
|
|
7
|
-
export declare const enum AvatarEmoteMask {
|
|
8
|
-
AEM_FULL_BODY = 0,
|
|
9
|
-
AEM_UPPER_BODY = 1
|
|
10
|
-
}
|
|
11
3
|
/**
|
|
12
4
|
* The AvatarShape component contains the information required to draw and animate avatar, acting as
|
|
13
5
|
* a simplified GLTF container for this specific case.
|
|
@@ -3,15 +3,6 @@ import Long from "long";
|
|
|
3
3
|
import _m0 from "protobufjs/minimal";
|
|
4
4
|
import { Color3 } from "../../common/colors.gen";
|
|
5
5
|
const protobufPackageSarasa = "decentraland.sdk.components";
|
|
6
|
-
/** Mask for which bones an animation applies to. */
|
|
7
|
-
/**
|
|
8
|
-
* @public
|
|
9
|
-
*/
|
|
10
|
-
export var AvatarEmoteMask;
|
|
11
|
-
(function (AvatarEmoteMask) {
|
|
12
|
-
AvatarEmoteMask[AvatarEmoteMask["AEM_FULL_BODY"] = 0] = "AEM_FULL_BODY";
|
|
13
|
-
AvatarEmoteMask[AvatarEmoteMask["AEM_UPPER_BODY"] = 1] = "AEM_UPPER_BODY";
|
|
14
|
-
})(AvatarEmoteMask || (AvatarEmoteMask = {}));
|
|
15
6
|
function createBasePBAvatarShape() {
|
|
16
7
|
return {
|
|
17
8
|
id: "",
|
package/dist/engine/entity.js
CHANGED
|
@@ -56,6 +56,16 @@ export var EntityState;
|
|
|
56
56
|
*/
|
|
57
57
|
EntityState[EntityState["Reserved"] = 3] = "Reserved";
|
|
58
58
|
})(EntityState || (EntityState = {}));
|
|
59
|
+
/**
|
|
60
|
+
* True when `entity`'s NUMBER falls in the renderer-reserved range, at any version.
|
|
61
|
+
*
|
|
62
|
+
* Masks rather than calling `EntityUtils.fromEntityId`, which allocates a tuple per call to
|
|
63
|
+
* read one number; this runs on every inbound CRDT message. `entity & MAX_U16` already lands
|
|
64
|
+
* in [0, 65535], so the `>>> 0` fromEntityId applies is a no-op here.
|
|
65
|
+
*/
|
|
66
|
+
function isReservedEntity(entity, reservedStaticEntities) {
|
|
67
|
+
return (entity & MAX_U16) < reservedStaticEntities;
|
|
68
|
+
}
|
|
59
69
|
/**
|
|
60
70
|
* @public
|
|
61
71
|
*/
|
|
@@ -90,7 +100,11 @@ export function createEntityContainer(opts) {
|
|
|
90
100
|
return generateNewEntity();
|
|
91
101
|
}
|
|
92
102
|
for (const [number, version] of removedEntities.getMap()) {
|
|
93
|
-
|
|
103
|
+
// Never recycle a renderer-reserved number: the renderer reissues those slots as
|
|
104
|
+
// toEntityId(number, version + 1) too, from the same stored version, so it would hand
|
|
105
|
+
// the scene an id belonging to a live remote player. Belt-and-braces — every writer
|
|
106
|
+
// into `removedEntities` refuses reserved numbers, so this cannot fire today.
|
|
107
|
+
if (number >= reservedStaticEntities && version < MAX_U16) {
|
|
94
108
|
const entity = EntityUtils.toEntityId(number, version + 1);
|
|
95
109
|
// If the entity is not being used, we can re-use it
|
|
96
110
|
// If the entity was removed in this tick, we're not counting for the usedEntities, but we have it in the toRemoveEntityArray
|
|
@@ -103,7 +117,7 @@ export function createEntityContainer(opts) {
|
|
|
103
117
|
return generateNewEntity();
|
|
104
118
|
}
|
|
105
119
|
function removeEntity(entity) {
|
|
106
|
-
if (entity
|
|
120
|
+
if (isReservedEntity(entity, reservedStaticEntities))
|
|
107
121
|
return false;
|
|
108
122
|
if (usedEntities.has(entity)) {
|
|
109
123
|
usedEntities.delete(entity);
|
|
@@ -126,6 +140,12 @@ export function createEntityContainer(opts) {
|
|
|
126
140
|
return arr;
|
|
127
141
|
}
|
|
128
142
|
function updateRemovedEntity(entity) {
|
|
143
|
+
// Called for EVERY inbound DELETE_ENTITY, including the renderer's tombstones for
|
|
144
|
+
// departed remote players — so this is the door reserved numbers would otherwise enter
|
|
145
|
+
// the free list through. They need no tombstone: getEntityState reports them Reserved
|
|
146
|
+
// before it consults `removedEntities`, so `Removed` is unreachable for them anyway.
|
|
147
|
+
if (isReservedEntity(entity, reservedStaticEntities))
|
|
148
|
+
return false;
|
|
129
149
|
const [n, v] = EntityUtils.fromEntityId(entity);
|
|
130
150
|
// Update the removed entities map
|
|
131
151
|
removedEntities.addTo(n, v);
|
|
@@ -136,6 +156,11 @@ export function createEntityContainer(opts) {
|
|
|
136
156
|
return true;
|
|
137
157
|
}
|
|
138
158
|
function updateUsedEntity(entity) {
|
|
159
|
+
// Same invariant as updateRemovedEntity. Unreachable from the CRDT path today
|
|
160
|
+
// (getEntityState returns `Reserved`, never `Unknown`), but the `v > 0` branch below
|
|
161
|
+
// would seed `removedEntities` with a reserved number.
|
|
162
|
+
if (isReservedEntity(entity, reservedStaticEntities))
|
|
163
|
+
return false;
|
|
139
164
|
const [n, v] = EntityUtils.fromEntityId(entity);
|
|
140
165
|
// if the entity was removed then abort fast
|
|
141
166
|
if (removedEntities.has(n, v))
|
|
@@ -151,10 +176,12 @@ export function createEntityContainer(opts) {
|
|
|
151
176
|
return true;
|
|
152
177
|
}
|
|
153
178
|
function getEntityState(entity) {
|
|
154
|
-
|
|
155
|
-
|
|
179
|
+
// Same guard as the three above, so `Engine.removeEntity` — which classifies via
|
|
180
|
+
// getEntityState — cannot disagree with whether this container releases the id.
|
|
181
|
+
if (isReservedEntity(entity, reservedStaticEntities)) {
|
|
156
182
|
return EntityState.Reserved;
|
|
157
183
|
}
|
|
184
|
+
const [n, v] = EntityUtils.fromEntityId(entity);
|
|
158
185
|
if (usedEntities.has(entity)) {
|
|
159
186
|
return EntityState.UsedEntity;
|
|
160
187
|
}
|
package/dist/engine/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { checkNotThenable } from '../runtime/invariant';
|
|
|
4
4
|
import { Schemas } from '../schemas';
|
|
5
5
|
import { crdtSceneSystem } from '../systems/crdt';
|
|
6
6
|
import { createComponentDefinitionFromSchema } from './lww-element-set-component-definition';
|
|
7
|
-
import { createEntityContainer } from './entity';
|
|
7
|
+
import { EntityState, EntityUtils, createEntityContainer } from './entity';
|
|
8
8
|
import { SystemContainer, SYSTEMS_REGULAR_PRIORITY } from './systems';
|
|
9
9
|
import { createValueSetComponentDefinitionFromSchema } from './grow-only-value-set-component-definition';
|
|
10
10
|
import { removeEntityWithChildren as removeEntityWithChildrenEngine } from '../runtime/helpers/tree';
|
|
@@ -12,6 +12,8 @@ import { CrdtMessageType } from '../serialization/crdt';
|
|
|
12
12
|
export * from './input';
|
|
13
13
|
export * from './readonly';
|
|
14
14
|
export * from './types';
|
|
15
|
+
/** RootEntity 0, PlayerEntity 1, CameraEntity 2 — see the engineInstance fields below. */
|
|
16
|
+
const NAMED_STATIC_ENTITIES = 3;
|
|
15
17
|
function preEngine(options) {
|
|
16
18
|
const entityContainer = options?.entityContainer ?? createEntityContainer();
|
|
17
19
|
const componentsDefinition = new Map();
|
|
@@ -28,6 +30,18 @@ function preEngine(options) {
|
|
|
28
30
|
return entity;
|
|
29
31
|
}
|
|
30
32
|
function removeEntity(entity) {
|
|
33
|
+
// The renderer streams the avatar range and drops the scene's deletes there, so purging
|
|
34
|
+
// locally is permanent: a one-shot component like PlayerIdentityData is never re-sent, and
|
|
35
|
+
// the entity is left as a moving Transform with no identity. The three named static
|
|
36
|
+
// entities are reserved too, but the renderer DOES apply scene deletes on them — that is
|
|
37
|
+
// how InputModifier.deleteFrom(engine.PlayerEntity) clears an input lock — so they must
|
|
38
|
+
// still be purged. Asking the container keeps this in step with whether it releases the
|
|
39
|
+
// id, including for a custom container with a different reserved range.
|
|
40
|
+
const [entityNumber] = EntityUtils.fromEntityId(entity);
|
|
41
|
+
const isAvatarEntity = entityNumber >= NAMED_STATIC_ENTITIES && entityContainer.getEntityState(entity) === EntityState.Reserved;
|
|
42
|
+
const released = entityContainer.removeEntity(entity);
|
|
43
|
+
if (isAvatarEntity)
|
|
44
|
+
return released;
|
|
31
45
|
for (const [, component] of componentsDefinition) {
|
|
32
46
|
// TODO: hack for the moment.
|
|
33
47
|
// We still need the NetworkEntity to forward this message to the SyncTransport.
|
|
@@ -36,7 +50,7 @@ function preEngine(options) {
|
|
|
36
50
|
continue;
|
|
37
51
|
component.entityDeleted(entity, true);
|
|
38
52
|
}
|
|
39
|
-
return
|
|
53
|
+
return released;
|
|
40
54
|
}
|
|
41
55
|
function removeEntityWithChildren(entity) {
|
|
42
56
|
return removeEntityWithChildrenEngine({ removeEntity, defineComponentFromSchema, getEntitiesWith, defineComponent }, entity);
|
|
@@ -260,7 +274,12 @@ export function Engine(options) {
|
|
|
260
274
|
RootEntity: 0,
|
|
261
275
|
PlayerEntity: 1,
|
|
262
276
|
CameraEntity: 2,
|
|
263
|
-
|
|
277
|
+
// Delegated, not aliased. A detached `entityContainer.getEntityState` reference binds
|
|
278
|
+
// `this` to the engine, so a custom IEntityContainer that uses `this` silently reports the
|
|
279
|
+
// wrong state through the public API while the engine itself, which calls the container
|
|
280
|
+
// directly, reports the right one. Harmless for the built-in closure-based container, but
|
|
281
|
+
// removeEntity now classifies through getEntityState, so the two must never diverge.
|
|
282
|
+
getEntityState: (entity) => partialEngine.entityContainer.getEntityState(entity),
|
|
264
283
|
addTransport: crdtSystem.addTransport,
|
|
265
284
|
entityContainer: partialEngine.entityContainer
|
|
266
285
|
};
|
package/dist/engine/types.d.ts
CHANGED
|
@@ -55,11 +55,18 @@ export interface IEngine {
|
|
|
55
55
|
* @public
|
|
56
56
|
* Remove all components of an entity
|
|
57
57
|
* @param entity - entity
|
|
58
|
+
* @returns whether the entity id was released for reuse. Ids in the renderer-reserved range
|
|
59
|
+
* are never released, at any version. Components are still purged for
|
|
60
|
+
* RootEntity/PlayerEntity/CameraEntity, but not for the avatar range.
|
|
58
61
|
*/
|
|
59
|
-
removeEntity(entity: Entity):
|
|
62
|
+
removeEntity(entity: Entity): boolean;
|
|
60
63
|
/**
|
|
61
64
|
* Remove all components of each entity in the tree made with Transform parenting
|
|
62
65
|
* @param entity - the root entity of the tree
|
|
66
|
+
*
|
|
67
|
+
* May complete only partially and does not report it: nodes in the renderer-reserved range
|
|
68
|
+
* are refused by `removeEntity`, so a reserved node anywhere in the tree survives while its
|
|
69
|
+
* descendants are removed — leaving its `Transform.parent` pointing at a removed entity.
|
|
63
70
|
*/
|
|
64
71
|
removeEntityWithChildren(entity: Entity): void;
|
|
65
72
|
/**
|
|
@@ -177,7 +177,8 @@ export function createTriggerAreaEventsSystem(engine) {
|
|
|
177
177
|
// Pass 2: synthesize per-tick onStay callbacks
|
|
178
178
|
// -----------------------------------------------------------------------
|
|
179
179
|
// Only run if an onStay callback is registered and there are tracked triggerers.
|
|
180
|
-
if (data.triggerCallbackMap.has(1 /* TriggerAreaEventType.TAET_STAY */) &&
|
|
180
|
+
if (data.triggerCallbackMap.has(1 /* TriggerAreaEventType.TAET_STAY */) &&
|
|
181
|
+
data.insideTriggerers.size > 0) {
|
|
181
182
|
const onStay = data.triggerCallbackMap.get(1 /* TriggerAreaEventType.TAET_STAY */);
|
|
182
183
|
const currentTimestamp = Date.now();
|
|
183
184
|
for (const [triggererEntity, cachedResult] of data.insideTriggerers) {
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import _m0 from "protobufjs/minimal";
|
|
2
2
|
import { Color3 } from "../../common/colors.gen";
|
|
3
|
-
/** Mask for which bones an animation applies to. */
|
|
4
|
-
/**
|
|
5
|
-
* @public
|
|
6
|
-
*/
|
|
7
|
-
export declare const enum AvatarEmoteMask {
|
|
8
|
-
AEM_FULL_BODY = 0,
|
|
9
|
-
AEM_UPPER_BODY = 1
|
|
10
|
-
}
|
|
11
3
|
/**
|
|
12
4
|
* The AvatarShape component contains the information required to draw and animate avatar, acting as
|
|
13
5
|
* a simplified GLTF container for this specific case.
|
|
@@ -3,21 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.PBAvatarShape =
|
|
6
|
+
exports.PBAvatarShape = void 0;
|
|
7
7
|
/* eslint-disable */
|
|
8
8
|
const long_1 = __importDefault(require("long"));
|
|
9
9
|
const minimal_1 = __importDefault(require("protobufjs/minimal"));
|
|
10
10
|
const colors_gen_1 = require("../../common/colors.gen");
|
|
11
11
|
const protobufPackageSarasa = "decentraland.sdk.components";
|
|
12
|
-
/** Mask for which bones an animation applies to. */
|
|
13
|
-
/**
|
|
14
|
-
* @public
|
|
15
|
-
*/
|
|
16
|
-
var AvatarEmoteMask;
|
|
17
|
-
(function (AvatarEmoteMask) {
|
|
18
|
-
AvatarEmoteMask[AvatarEmoteMask["AEM_FULL_BODY"] = 0] = "AEM_FULL_BODY";
|
|
19
|
-
AvatarEmoteMask[AvatarEmoteMask["AEM_UPPER_BODY"] = 1] = "AEM_UPPER_BODY";
|
|
20
|
-
})(AvatarEmoteMask = exports.AvatarEmoteMask || (exports.AvatarEmoteMask = {}));
|
|
21
12
|
function createBasePBAvatarShape() {
|
|
22
13
|
return {
|
|
23
14
|
id: "",
|
|
@@ -59,6 +59,16 @@ var EntityState;
|
|
|
59
59
|
*/
|
|
60
60
|
EntityState[EntityState["Reserved"] = 3] = "Reserved";
|
|
61
61
|
})(EntityState = exports.EntityState || (exports.EntityState = {}));
|
|
62
|
+
/**
|
|
63
|
+
* True when `entity`'s NUMBER falls in the renderer-reserved range, at any version.
|
|
64
|
+
*
|
|
65
|
+
* Masks rather than calling `EntityUtils.fromEntityId`, which allocates a tuple per call to
|
|
66
|
+
* read one number; this runs on every inbound CRDT message. `entity & MAX_U16` already lands
|
|
67
|
+
* in [0, 65535], so the `>>> 0` fromEntityId applies is a no-op here.
|
|
68
|
+
*/
|
|
69
|
+
function isReservedEntity(entity, reservedStaticEntities) {
|
|
70
|
+
return (entity & exports.MAX_U16) < reservedStaticEntities;
|
|
71
|
+
}
|
|
62
72
|
/**
|
|
63
73
|
* @public
|
|
64
74
|
*/
|
|
@@ -93,7 +103,11 @@ function createEntityContainer(opts) {
|
|
|
93
103
|
return generateNewEntity();
|
|
94
104
|
}
|
|
95
105
|
for (const [number, version] of removedEntities.getMap()) {
|
|
96
|
-
|
|
106
|
+
// Never recycle a renderer-reserved number: the renderer reissues those slots as
|
|
107
|
+
// toEntityId(number, version + 1) too, from the same stored version, so it would hand
|
|
108
|
+
// the scene an id belonging to a live remote player. Belt-and-braces — every writer
|
|
109
|
+
// into `removedEntities` refuses reserved numbers, so this cannot fire today.
|
|
110
|
+
if (number >= reservedStaticEntities && version < exports.MAX_U16) {
|
|
97
111
|
const entity = EntityUtils.toEntityId(number, version + 1);
|
|
98
112
|
// If the entity is not being used, we can re-use it
|
|
99
113
|
// If the entity was removed in this tick, we're not counting for the usedEntities, but we have it in the toRemoveEntityArray
|
|
@@ -106,7 +120,7 @@ function createEntityContainer(opts) {
|
|
|
106
120
|
return generateNewEntity();
|
|
107
121
|
}
|
|
108
122
|
function removeEntity(entity) {
|
|
109
|
-
if (entity
|
|
123
|
+
if (isReservedEntity(entity, reservedStaticEntities))
|
|
110
124
|
return false;
|
|
111
125
|
if (usedEntities.has(entity)) {
|
|
112
126
|
usedEntities.delete(entity);
|
|
@@ -129,6 +143,12 @@ function createEntityContainer(opts) {
|
|
|
129
143
|
return arr;
|
|
130
144
|
}
|
|
131
145
|
function updateRemovedEntity(entity) {
|
|
146
|
+
// Called for EVERY inbound DELETE_ENTITY, including the renderer's tombstones for
|
|
147
|
+
// departed remote players — so this is the door reserved numbers would otherwise enter
|
|
148
|
+
// the free list through. They need no tombstone: getEntityState reports them Reserved
|
|
149
|
+
// before it consults `removedEntities`, so `Removed` is unreachable for them anyway.
|
|
150
|
+
if (isReservedEntity(entity, reservedStaticEntities))
|
|
151
|
+
return false;
|
|
132
152
|
const [n, v] = EntityUtils.fromEntityId(entity);
|
|
133
153
|
// Update the removed entities map
|
|
134
154
|
removedEntities.addTo(n, v);
|
|
@@ -139,6 +159,11 @@ function createEntityContainer(opts) {
|
|
|
139
159
|
return true;
|
|
140
160
|
}
|
|
141
161
|
function updateUsedEntity(entity) {
|
|
162
|
+
// Same invariant as updateRemovedEntity. Unreachable from the CRDT path today
|
|
163
|
+
// (getEntityState returns `Reserved`, never `Unknown`), but the `v > 0` branch below
|
|
164
|
+
// would seed `removedEntities` with a reserved number.
|
|
165
|
+
if (isReservedEntity(entity, reservedStaticEntities))
|
|
166
|
+
return false;
|
|
142
167
|
const [n, v] = EntityUtils.fromEntityId(entity);
|
|
143
168
|
// if the entity was removed then abort fast
|
|
144
169
|
if (removedEntities.has(n, v))
|
|
@@ -154,10 +179,12 @@ function createEntityContainer(opts) {
|
|
|
154
179
|
return true;
|
|
155
180
|
}
|
|
156
181
|
function getEntityState(entity) {
|
|
157
|
-
|
|
158
|
-
|
|
182
|
+
// Same guard as the three above, so `Engine.removeEntity` — which classifies via
|
|
183
|
+
// getEntityState — cannot disagree with whether this container releases the id.
|
|
184
|
+
if (isReservedEntity(entity, reservedStaticEntities)) {
|
|
159
185
|
return EntityState.Reserved;
|
|
160
186
|
}
|
|
187
|
+
const [n, v] = EntityUtils.fromEntityId(entity);
|
|
161
188
|
if (usedEntities.has(entity)) {
|
|
162
189
|
return EntityState.UsedEntity;
|
|
163
190
|
}
|
package/dist-cjs/engine/index.js
CHANGED
|
@@ -41,6 +41,8 @@ const crdt_2 = require("../serialization/crdt");
|
|
|
41
41
|
__exportStar(require("./input"), exports);
|
|
42
42
|
__exportStar(require("./readonly"), exports);
|
|
43
43
|
__exportStar(require("./types"), exports);
|
|
44
|
+
/** RootEntity 0, PlayerEntity 1, CameraEntity 2 — see the engineInstance fields below. */
|
|
45
|
+
const NAMED_STATIC_ENTITIES = 3;
|
|
44
46
|
function preEngine(options) {
|
|
45
47
|
const entityContainer = options?.entityContainer ?? (0, entity_1.createEntityContainer)();
|
|
46
48
|
const componentsDefinition = new Map();
|
|
@@ -57,6 +59,18 @@ function preEngine(options) {
|
|
|
57
59
|
return entity;
|
|
58
60
|
}
|
|
59
61
|
function removeEntity(entity) {
|
|
62
|
+
// The renderer streams the avatar range and drops the scene's deletes there, so purging
|
|
63
|
+
// locally is permanent: a one-shot component like PlayerIdentityData is never re-sent, and
|
|
64
|
+
// the entity is left as a moving Transform with no identity. The three named static
|
|
65
|
+
// entities are reserved too, but the renderer DOES apply scene deletes on them — that is
|
|
66
|
+
// how InputModifier.deleteFrom(engine.PlayerEntity) clears an input lock — so they must
|
|
67
|
+
// still be purged. Asking the container keeps this in step with whether it releases the
|
|
68
|
+
// id, including for a custom container with a different reserved range.
|
|
69
|
+
const [entityNumber] = entity_1.EntityUtils.fromEntityId(entity);
|
|
70
|
+
const isAvatarEntity = entityNumber >= NAMED_STATIC_ENTITIES && entityContainer.getEntityState(entity) === entity_1.EntityState.Reserved;
|
|
71
|
+
const released = entityContainer.removeEntity(entity);
|
|
72
|
+
if (isAvatarEntity)
|
|
73
|
+
return released;
|
|
60
74
|
for (const [, component] of componentsDefinition) {
|
|
61
75
|
// TODO: hack for the moment.
|
|
62
76
|
// We still need the NetworkEntity to forward this message to the SyncTransport.
|
|
@@ -65,7 +79,7 @@ function preEngine(options) {
|
|
|
65
79
|
continue;
|
|
66
80
|
component.entityDeleted(entity, true);
|
|
67
81
|
}
|
|
68
|
-
return
|
|
82
|
+
return released;
|
|
69
83
|
}
|
|
70
84
|
function removeEntityWithChildren(entity) {
|
|
71
85
|
return (0, tree_1.removeEntityWithChildren)({ removeEntity, defineComponentFromSchema, getEntitiesWith, defineComponent }, entity);
|
|
@@ -289,7 +303,12 @@ function Engine(options) {
|
|
|
289
303
|
RootEntity: 0,
|
|
290
304
|
PlayerEntity: 1,
|
|
291
305
|
CameraEntity: 2,
|
|
292
|
-
|
|
306
|
+
// Delegated, not aliased. A detached `entityContainer.getEntityState` reference binds
|
|
307
|
+
// `this` to the engine, so a custom IEntityContainer that uses `this` silently reports the
|
|
308
|
+
// wrong state through the public API while the engine itself, which calls the container
|
|
309
|
+
// directly, reports the right one. Harmless for the built-in closure-based container, but
|
|
310
|
+
// removeEntity now classifies through getEntityState, so the two must never diverge.
|
|
311
|
+
getEntityState: (entity) => partialEngine.entityContainer.getEntityState(entity),
|
|
293
312
|
addTransport: crdtSystem.addTransport,
|
|
294
313
|
entityContainer: partialEngine.entityContainer
|
|
295
314
|
};
|
|
@@ -55,11 +55,18 @@ export interface IEngine {
|
|
|
55
55
|
* @public
|
|
56
56
|
* Remove all components of an entity
|
|
57
57
|
* @param entity - entity
|
|
58
|
+
* @returns whether the entity id was released for reuse. Ids in the renderer-reserved range
|
|
59
|
+
* are never released, at any version. Components are still purged for
|
|
60
|
+
* RootEntity/PlayerEntity/CameraEntity, but not for the avatar range.
|
|
58
61
|
*/
|
|
59
|
-
removeEntity(entity: Entity):
|
|
62
|
+
removeEntity(entity: Entity): boolean;
|
|
60
63
|
/**
|
|
61
64
|
* Remove all components of each entity in the tree made with Transform parenting
|
|
62
65
|
* @param entity - the root entity of the tree
|
|
66
|
+
*
|
|
67
|
+
* May complete only partially and does not report it: nodes in the renderer-reserved range
|
|
68
|
+
* are refused by `removeEntity`, so a reserved node anywhere in the tree survives while its
|
|
69
|
+
* descendants are removed — leaving its `Transform.parent` pointing at a removed entity.
|
|
63
70
|
*/
|
|
64
71
|
removeEntityWithChildren(entity: Entity): void;
|
|
65
72
|
/**
|
|
@@ -203,7 +203,8 @@ function createTriggerAreaEventsSystem(engine) {
|
|
|
203
203
|
// Pass 2: synthesize per-tick onStay callbacks
|
|
204
204
|
// -----------------------------------------------------------------------
|
|
205
205
|
// Only run if an onStay callback is registered and there are tracked triggerers.
|
|
206
|
-
if (data.triggerCallbackMap.has(1 /* TriggerAreaEventType.TAET_STAY */) &&
|
|
206
|
+
if (data.triggerCallbackMap.has(1 /* TriggerAreaEventType.TAET_STAY */) &&
|
|
207
|
+
data.insideTriggerers.size > 0) {
|
|
207
208
|
const onStay = data.triggerCallbackMap.get(1 /* TriggerAreaEventType.TAET_STAY */);
|
|
208
209
|
const currentTimestamp = Date.now();
|
|
209
210
|
for (const [triggererEntity, cachedResult] of data.insideTriggerers) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dcl/ecs",
|
|
3
3
|
"description": "Decentraland ECS",
|
|
4
|
-
"version": "7.26.1-
|
|
4
|
+
"version": "7.26.1-32157237851.commit-e712ef7",
|
|
5
5
|
"author": "DCL",
|
|
6
6
|
"bugs": "https://github.com/decentraland/ecs/issues",
|
|
7
7
|
"files": [
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"dependencies": {},
|
|
35
35
|
"types": "./dist/index.d.ts",
|
|
36
36
|
"typings": "./dist/index.d.ts",
|
|
37
|
-
"commit": "
|
|
37
|
+
"commit": "e712ef71c81b53f1125e7b9658f3751ab455b63e"
|
|
38
38
|
}
|