@dcl/ecs 7.23.2-25670347846.commit-ae6c2f7 → 7.23.2
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.
|
@@ -26,6 +26,11 @@ export interface TriggerAreaEventsSystem {
|
|
|
26
26
|
* Execute callback when an entity stays in the Trigger Area
|
|
27
27
|
* @param entity - The entity that already has the TriggerArea component
|
|
28
28
|
* @param cb - Function to execute the 'Stay' type of result is detected
|
|
29
|
+
*
|
|
30
|
+
* Note: stay callbacks are synthesized by the SDK on every tick between a wire ENTER and a wire EXIT.
|
|
31
|
+
* Wire-level TAET_STAY events (still emitted by legacy Explorers) are ignored entirely — they neither
|
|
32
|
+
* fire callbacks nor mutate state. The SDK is the sole source of onTriggerStay dispatches, driven
|
|
33
|
+
* from the ENTER/EXIT state machine.
|
|
29
34
|
*/
|
|
30
35
|
onTriggerStay(entity: Entity, cb: TriggerAreaEventSystemCallback): void;
|
|
31
36
|
/**
|
|
@@ -1,10 +1,57 @@
|
|
|
1
1
|
import * as components from '../components';
|
|
2
2
|
import { EntityState } from '../engine/entity';
|
|
3
|
+
/**
|
|
4
|
+
* Builds a synthetic PBTriggerAreaResult for a per-tick onStay callback.
|
|
5
|
+
*
|
|
6
|
+
* Transform components are resolved at call time so that scene-owned entities report
|
|
7
|
+
* up-to-date position/rotation/scale. For player-avatar triggerers (reserved entities
|
|
8
|
+
* without a scene-side Transform), there is no scene Transform component, so the cached
|
|
9
|
+
* values from the last ENTER or wire-STAY event are used as-is. These cached values may
|
|
10
|
+
* be slightly stale for the current frame — this is expected and acceptable for the
|
|
11
|
+
* avatar case.
|
|
12
|
+
*/
|
|
13
|
+
function buildSyntheticStayResult(cached, triggerAreaEntity, triggererEntity, currentTimestamp, Transform) {
|
|
14
|
+
// Shallow-clone the trigger sub-object so we can mutate it.
|
|
15
|
+
const trigger = cached.trigger
|
|
16
|
+
? {
|
|
17
|
+
entity: cached.trigger.entity,
|
|
18
|
+
layers: cached.trigger.layers,
|
|
19
|
+
position: cached.trigger.position ? { ...cached.trigger.position } : undefined,
|
|
20
|
+
rotation: cached.trigger.rotation ? { ...cached.trigger.rotation } : undefined,
|
|
21
|
+
scale: cached.trigger.scale ? { ...cached.trigger.scale } : undefined
|
|
22
|
+
}
|
|
23
|
+
: undefined;
|
|
24
|
+
// Build the cloned result with a forced TAET_STAY eventType and refreshed timestamp.
|
|
25
|
+
const result = {
|
|
26
|
+
triggeredEntity: cached.triggeredEntity,
|
|
27
|
+
triggeredEntityPosition: cached.triggeredEntityPosition ? { ...cached.triggeredEntityPosition } : undefined,
|
|
28
|
+
triggeredEntityRotation: cached.triggeredEntityRotation ? { ...cached.triggeredEntityRotation } : undefined,
|
|
29
|
+
eventType: 1 /* TriggerAreaEventType.TAET_STAY */,
|
|
30
|
+
timestamp: currentTimestamp,
|
|
31
|
+
trigger
|
|
32
|
+
};
|
|
33
|
+
// Refresh trigger-area entity transform when it is scene-owned.
|
|
34
|
+
const triggerAreaTransform = Transform.getOrNull(triggerAreaEntity);
|
|
35
|
+
if (triggerAreaTransform !== null) {
|
|
36
|
+
result.triggeredEntityPosition = { ...triggerAreaTransform.position };
|
|
37
|
+
result.triggeredEntityRotation = { ...triggerAreaTransform.rotation };
|
|
38
|
+
}
|
|
39
|
+
// Refresh triggerer transform when it is scene-owned.
|
|
40
|
+
// For player-avatar entities (reserved, no scene-side Transform) the cached values are kept.
|
|
41
|
+
const triggererTransform = Transform.getOrNull(triggererEntity);
|
|
42
|
+
if (triggererTransform !== null && result.trigger) {
|
|
43
|
+
result.trigger.position = { ...triggererTransform.position };
|
|
44
|
+
result.trigger.rotation = { ...triggererTransform.rotation };
|
|
45
|
+
result.trigger.scale = { ...triggererTransform.scale };
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
3
49
|
/**
|
|
4
50
|
* @internal
|
|
5
51
|
*/
|
|
6
52
|
export function createTriggerAreaEventsSystem(engine) {
|
|
7
53
|
const triggerAreaResultComponent = components.TriggerAreaResult(engine);
|
|
54
|
+
const Transform = components.Transform(engine);
|
|
8
55
|
const entitiesMap = new Map();
|
|
9
56
|
function hasCallbacksMap(entity) {
|
|
10
57
|
return entitiesMap.has(entity) && entitiesMap.get(entity) !== undefined;
|
|
@@ -16,7 +63,8 @@ export function createTriggerAreaEventsSystem(engine) {
|
|
|
16
63
|
else {
|
|
17
64
|
entitiesMap.set(entity, {
|
|
18
65
|
triggerCallbackMap: new Map([[triggerType, callback]]),
|
|
19
|
-
lastConsumedTimestamp: -1
|
|
66
|
+
lastConsumedTimestamp: -1,
|
|
67
|
+
insideTriggerers: new Map()
|
|
20
68
|
});
|
|
21
69
|
}
|
|
22
70
|
}
|
|
@@ -25,7 +73,9 @@ export function createTriggerAreaEventsSystem(engine) {
|
|
|
25
73
|
return;
|
|
26
74
|
const triggerCallbackMap = entitiesMap.get(entity).triggerCallbackMap;
|
|
27
75
|
triggerCallbackMap.delete(triggerType);
|
|
28
|
-
// Remove entity if no more trigger callbacks are registered
|
|
76
|
+
// Remove entity if no more trigger callbacks are registered.
|
|
77
|
+
// insideTriggerers is intentionally left populated so that re-subscription picks up
|
|
78
|
+
// in-flight sessions without missing the first synthesized onStay.
|
|
29
79
|
if (triggerCallbackMap.size === 0)
|
|
30
80
|
entitiesMap.delete(entity);
|
|
31
81
|
}
|
|
@@ -55,51 +105,88 @@ export function createTriggerAreaEventsSystem(engine) {
|
|
|
55
105
|
continue;
|
|
56
106
|
}
|
|
57
107
|
const result = triggerAreaResultComponent.get(entity);
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
108
|
+
// -----------------------------------------------------------------------
|
|
109
|
+
// Pass 1: drain new GOVS events
|
|
110
|
+
// -----------------------------------------------------------------------
|
|
111
|
+
// The Explorer may be taking time before the result component is put.
|
|
112
|
+
if (result.size > 0) {
|
|
113
|
+
const values = Array.from(result.values());
|
|
114
|
+
// Determine starting index for new values (more than one could be added between System updates).
|
|
115
|
+
// Search backwards to find the anchor at lastConsumedTimestamp.
|
|
116
|
+
let startIndex = 0;
|
|
117
|
+
if (data.lastConsumedTimestamp >= 0) {
|
|
118
|
+
const newestTimestamp = values[values.length - 1].timestamp;
|
|
119
|
+
// If nothing new, skip processing.
|
|
120
|
+
if (newestTimestamp > data.lastConsumedTimestamp) {
|
|
121
|
+
// Find index of value with the lastConsumedTimestamp.
|
|
122
|
+
let i = values.length - 2;
|
|
123
|
+
while (i >= 0 && values[i].timestamp > data.lastConsumedTimestamp)
|
|
124
|
+
i--;
|
|
125
|
+
// Mark the following value index as the starting point to trigger all the new value callbacks.
|
|
126
|
+
startIndex = i + 1;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// No new events — skip to Pass 2.
|
|
130
|
+
startIndex = values.length;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (startIndex < values.length) {
|
|
134
|
+
// Process new wire events in chronological order.
|
|
135
|
+
for (let i = startIndex; i < values.length; i++) {
|
|
136
|
+
const event = values[i];
|
|
137
|
+
switch (event.eventType) {
|
|
138
|
+
case 0 /* TriggerAreaEventType.TAET_ENTER */:
|
|
139
|
+
// Update in-flight tracking before firing the callback.
|
|
140
|
+
data.insideTriggerers.set(event.trigger.entity, {
|
|
141
|
+
triggeredEntity: event.triggeredEntity,
|
|
142
|
+
triggeredEntityPosition: event.triggeredEntityPosition
|
|
143
|
+
? { ...event.triggeredEntityPosition }
|
|
144
|
+
: undefined,
|
|
145
|
+
triggeredEntityRotation: event.triggeredEntityRotation
|
|
146
|
+
? { ...event.triggeredEntityRotation }
|
|
147
|
+
: undefined,
|
|
148
|
+
eventType: event.eventType,
|
|
149
|
+
timestamp: event.timestamp,
|
|
150
|
+
trigger: event.trigger
|
|
151
|
+
? {
|
|
152
|
+
entity: event.trigger.entity,
|
|
153
|
+
layers: event.trigger.layers,
|
|
154
|
+
position: event.trigger.position ? { ...event.trigger.position } : undefined,
|
|
155
|
+
rotation: event.trigger.rotation ? { ...event.trigger.rotation } : undefined,
|
|
156
|
+
scale: event.trigger.scale ? { ...event.trigger.scale } : undefined
|
|
157
|
+
}
|
|
158
|
+
: undefined
|
|
159
|
+
});
|
|
160
|
+
if (data.triggerCallbackMap.has(0 /* TriggerAreaEventType.TAET_ENTER */)) {
|
|
161
|
+
data.triggerCallbackMap.get(0 /* TriggerAreaEventType.TAET_ENTER */)(event);
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
case 2 /* TriggerAreaEventType.TAET_EXIT */:
|
|
165
|
+
data.insideTriggerers.delete(event.trigger.entity);
|
|
166
|
+
if (data.triggerCallbackMap.has(2 /* TriggerAreaEventType.TAET_EXIT */)) {
|
|
167
|
+
data.triggerCallbackMap.get(2 /* TriggerAreaEventType.TAET_EXIT */)(event);
|
|
168
|
+
}
|
|
169
|
+
break;
|
|
170
|
+
// Wire-level TAET_STAY and any unknown event types are ignored — no callback, no state mutation.
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
data.lastConsumedTimestamp = values[values.length - 1].timestamp;
|
|
70
174
|
}
|
|
71
|
-
// Find index of value with the lastConsumedTimestamp
|
|
72
|
-
let i = values.length - 2;
|
|
73
|
-
while (i >= 0 && values[i].timestamp > data.lastConsumedTimestamp)
|
|
74
|
-
i--;
|
|
75
|
-
// Mark the following value index as the starting point to trigger all the new value callbacks
|
|
76
|
-
startIndex = i + 1;
|
|
77
175
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
case 1 /* TriggerAreaEventType.TAET_STAY */:
|
|
89
|
-
if (!data.triggerCallbackMap.has(1 /* TriggerAreaEventType.TAET_STAY */))
|
|
90
|
-
continue;
|
|
91
|
-
data.triggerCallbackMap.get(1 /* TriggerAreaEventType.TAET_STAY */)(values[i]);
|
|
92
|
-
break;
|
|
93
|
-
case 2 /* TriggerAreaEventType.TAET_EXIT */:
|
|
94
|
-
if (!data.triggerCallbackMap.has(2 /* TriggerAreaEventType.TAET_EXIT */))
|
|
95
|
-
continue;
|
|
96
|
-
data.triggerCallbackMap.get(2 /* TriggerAreaEventType.TAET_EXIT */)(values[i]);
|
|
97
|
-
break;
|
|
176
|
+
// -----------------------------------------------------------------------
|
|
177
|
+
// Pass 2: synthesize per-tick onStay callbacks
|
|
178
|
+
// -----------------------------------------------------------------------
|
|
179
|
+
// Only run if an onStay callback is registered and there are tracked triggerers.
|
|
180
|
+
if (data.triggerCallbackMap.has(1 /* TriggerAreaEventType.TAET_STAY */) &&
|
|
181
|
+
data.insideTriggerers.size > 0) {
|
|
182
|
+
const onStay = data.triggerCallbackMap.get(1 /* TriggerAreaEventType.TAET_STAY */);
|
|
183
|
+
const currentTimestamp = Date.now();
|
|
184
|
+
for (const [triggererEntity, cachedResult] of data.insideTriggerers) {
|
|
185
|
+
onStay(buildSyntheticStayResult(cachedResult, entity, triggererEntity, currentTimestamp, Transform));
|
|
98
186
|
}
|
|
99
187
|
}
|
|
100
|
-
data.lastConsumedTimestamp = values[values.length - 1].timestamp;
|
|
101
188
|
}
|
|
102
|
-
// Clean up garbage entries
|
|
189
|
+
// Clean up garbage entries.
|
|
103
190
|
garbageEntries.forEach((garbageEntity) => entitiesMap.delete(garbageEntity));
|
|
104
191
|
});
|
|
105
192
|
return {
|
|
@@ -26,6 +26,11 @@ export interface TriggerAreaEventsSystem {
|
|
|
26
26
|
* Execute callback when an entity stays in the Trigger Area
|
|
27
27
|
* @param entity - The entity that already has the TriggerArea component
|
|
28
28
|
* @param cb - Function to execute the 'Stay' type of result is detected
|
|
29
|
+
*
|
|
30
|
+
* Note: stay callbacks are synthesized by the SDK on every tick between a wire ENTER and a wire EXIT.
|
|
31
|
+
* Wire-level TAET_STAY events (still emitted by legacy Explorers) are ignored entirely — they neither
|
|
32
|
+
* fire callbacks nor mutate state. The SDK is the sole source of onTriggerStay dispatches, driven
|
|
33
|
+
* from the ENTER/EXIT state machine.
|
|
29
34
|
*/
|
|
30
35
|
onTriggerStay(entity: Entity, cb: TriggerAreaEventSystemCallback): void;
|
|
31
36
|
/**
|
|
@@ -26,11 +26,58 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.createTriggerAreaEventsSystem = void 0;
|
|
27
27
|
const components = __importStar(require("../components"));
|
|
28
28
|
const entity_1 = require("../engine/entity");
|
|
29
|
+
/**
|
|
30
|
+
* Builds a synthetic PBTriggerAreaResult for a per-tick onStay callback.
|
|
31
|
+
*
|
|
32
|
+
* Transform components are resolved at call time so that scene-owned entities report
|
|
33
|
+
* up-to-date position/rotation/scale. For player-avatar triggerers (reserved entities
|
|
34
|
+
* without a scene-side Transform), there is no scene Transform component, so the cached
|
|
35
|
+
* values from the last ENTER or wire-STAY event are used as-is. These cached values may
|
|
36
|
+
* be slightly stale for the current frame — this is expected and acceptable for the
|
|
37
|
+
* avatar case.
|
|
38
|
+
*/
|
|
39
|
+
function buildSyntheticStayResult(cached, triggerAreaEntity, triggererEntity, currentTimestamp, Transform) {
|
|
40
|
+
// Shallow-clone the trigger sub-object so we can mutate it.
|
|
41
|
+
const trigger = cached.trigger
|
|
42
|
+
? {
|
|
43
|
+
entity: cached.trigger.entity,
|
|
44
|
+
layers: cached.trigger.layers,
|
|
45
|
+
position: cached.trigger.position ? { ...cached.trigger.position } : undefined,
|
|
46
|
+
rotation: cached.trigger.rotation ? { ...cached.trigger.rotation } : undefined,
|
|
47
|
+
scale: cached.trigger.scale ? { ...cached.trigger.scale } : undefined
|
|
48
|
+
}
|
|
49
|
+
: undefined;
|
|
50
|
+
// Build the cloned result with a forced TAET_STAY eventType and refreshed timestamp.
|
|
51
|
+
const result = {
|
|
52
|
+
triggeredEntity: cached.triggeredEntity,
|
|
53
|
+
triggeredEntityPosition: cached.triggeredEntityPosition ? { ...cached.triggeredEntityPosition } : undefined,
|
|
54
|
+
triggeredEntityRotation: cached.triggeredEntityRotation ? { ...cached.triggeredEntityRotation } : undefined,
|
|
55
|
+
eventType: 1 /* TriggerAreaEventType.TAET_STAY */,
|
|
56
|
+
timestamp: currentTimestamp,
|
|
57
|
+
trigger
|
|
58
|
+
};
|
|
59
|
+
// Refresh trigger-area entity transform when it is scene-owned.
|
|
60
|
+
const triggerAreaTransform = Transform.getOrNull(triggerAreaEntity);
|
|
61
|
+
if (triggerAreaTransform !== null) {
|
|
62
|
+
result.triggeredEntityPosition = { ...triggerAreaTransform.position };
|
|
63
|
+
result.triggeredEntityRotation = { ...triggerAreaTransform.rotation };
|
|
64
|
+
}
|
|
65
|
+
// Refresh triggerer transform when it is scene-owned.
|
|
66
|
+
// For player-avatar entities (reserved, no scene-side Transform) the cached values are kept.
|
|
67
|
+
const triggererTransform = Transform.getOrNull(triggererEntity);
|
|
68
|
+
if (triggererTransform !== null && result.trigger) {
|
|
69
|
+
result.trigger.position = { ...triggererTransform.position };
|
|
70
|
+
result.trigger.rotation = { ...triggererTransform.rotation };
|
|
71
|
+
result.trigger.scale = { ...triggererTransform.scale };
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
29
75
|
/**
|
|
30
76
|
* @internal
|
|
31
77
|
*/
|
|
32
78
|
function createTriggerAreaEventsSystem(engine) {
|
|
33
79
|
const triggerAreaResultComponent = components.TriggerAreaResult(engine);
|
|
80
|
+
const Transform = components.Transform(engine);
|
|
34
81
|
const entitiesMap = new Map();
|
|
35
82
|
function hasCallbacksMap(entity) {
|
|
36
83
|
return entitiesMap.has(entity) && entitiesMap.get(entity) !== undefined;
|
|
@@ -42,7 +89,8 @@ function createTriggerAreaEventsSystem(engine) {
|
|
|
42
89
|
else {
|
|
43
90
|
entitiesMap.set(entity, {
|
|
44
91
|
triggerCallbackMap: new Map([[triggerType, callback]]),
|
|
45
|
-
lastConsumedTimestamp: -1
|
|
92
|
+
lastConsumedTimestamp: -1,
|
|
93
|
+
insideTriggerers: new Map()
|
|
46
94
|
});
|
|
47
95
|
}
|
|
48
96
|
}
|
|
@@ -51,7 +99,9 @@ function createTriggerAreaEventsSystem(engine) {
|
|
|
51
99
|
return;
|
|
52
100
|
const triggerCallbackMap = entitiesMap.get(entity).triggerCallbackMap;
|
|
53
101
|
triggerCallbackMap.delete(triggerType);
|
|
54
|
-
// Remove entity if no more trigger callbacks are registered
|
|
102
|
+
// Remove entity if no more trigger callbacks are registered.
|
|
103
|
+
// insideTriggerers is intentionally left populated so that re-subscription picks up
|
|
104
|
+
// in-flight sessions without missing the first synthesized onStay.
|
|
55
105
|
if (triggerCallbackMap.size === 0)
|
|
56
106
|
entitiesMap.delete(entity);
|
|
57
107
|
}
|
|
@@ -81,51 +131,88 @@ function createTriggerAreaEventsSystem(engine) {
|
|
|
81
131
|
continue;
|
|
82
132
|
}
|
|
83
133
|
const result = triggerAreaResultComponent.get(entity);
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
134
|
+
// -----------------------------------------------------------------------
|
|
135
|
+
// Pass 1: drain new GOVS events
|
|
136
|
+
// -----------------------------------------------------------------------
|
|
137
|
+
// The Explorer may be taking time before the result component is put.
|
|
138
|
+
if (result.size > 0) {
|
|
139
|
+
const values = Array.from(result.values());
|
|
140
|
+
// Determine starting index for new values (more than one could be added between System updates).
|
|
141
|
+
// Search backwards to find the anchor at lastConsumedTimestamp.
|
|
142
|
+
let startIndex = 0;
|
|
143
|
+
if (data.lastConsumedTimestamp >= 0) {
|
|
144
|
+
const newestTimestamp = values[values.length - 1].timestamp;
|
|
145
|
+
// If nothing new, skip processing.
|
|
146
|
+
if (newestTimestamp > data.lastConsumedTimestamp) {
|
|
147
|
+
// Find index of value with the lastConsumedTimestamp.
|
|
148
|
+
let i = values.length - 2;
|
|
149
|
+
while (i >= 0 && values[i].timestamp > data.lastConsumedTimestamp)
|
|
150
|
+
i--;
|
|
151
|
+
// Mark the following value index as the starting point to trigger all the new value callbacks.
|
|
152
|
+
startIndex = i + 1;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
// No new events — skip to Pass 2.
|
|
156
|
+
startIndex = values.length;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (startIndex < values.length) {
|
|
160
|
+
// Process new wire events in chronological order.
|
|
161
|
+
for (let i = startIndex; i < values.length; i++) {
|
|
162
|
+
const event = values[i];
|
|
163
|
+
switch (event.eventType) {
|
|
164
|
+
case 0 /* TriggerAreaEventType.TAET_ENTER */:
|
|
165
|
+
// Update in-flight tracking before firing the callback.
|
|
166
|
+
data.insideTriggerers.set(event.trigger.entity, {
|
|
167
|
+
triggeredEntity: event.triggeredEntity,
|
|
168
|
+
triggeredEntityPosition: event.triggeredEntityPosition
|
|
169
|
+
? { ...event.triggeredEntityPosition }
|
|
170
|
+
: undefined,
|
|
171
|
+
triggeredEntityRotation: event.triggeredEntityRotation
|
|
172
|
+
? { ...event.triggeredEntityRotation }
|
|
173
|
+
: undefined,
|
|
174
|
+
eventType: event.eventType,
|
|
175
|
+
timestamp: event.timestamp,
|
|
176
|
+
trigger: event.trigger
|
|
177
|
+
? {
|
|
178
|
+
entity: event.trigger.entity,
|
|
179
|
+
layers: event.trigger.layers,
|
|
180
|
+
position: event.trigger.position ? { ...event.trigger.position } : undefined,
|
|
181
|
+
rotation: event.trigger.rotation ? { ...event.trigger.rotation } : undefined,
|
|
182
|
+
scale: event.trigger.scale ? { ...event.trigger.scale } : undefined
|
|
183
|
+
}
|
|
184
|
+
: undefined
|
|
185
|
+
});
|
|
186
|
+
if (data.triggerCallbackMap.has(0 /* TriggerAreaEventType.TAET_ENTER */)) {
|
|
187
|
+
data.triggerCallbackMap.get(0 /* TriggerAreaEventType.TAET_ENTER */)(event);
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
case 2 /* TriggerAreaEventType.TAET_EXIT */:
|
|
191
|
+
data.insideTriggerers.delete(event.trigger.entity);
|
|
192
|
+
if (data.triggerCallbackMap.has(2 /* TriggerAreaEventType.TAET_EXIT */)) {
|
|
193
|
+
data.triggerCallbackMap.get(2 /* TriggerAreaEventType.TAET_EXIT */)(event);
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
196
|
+
// Wire-level TAET_STAY and any unknown event types are ignored — no callback, no state mutation.
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
data.lastConsumedTimestamp = values[values.length - 1].timestamp;
|
|
96
200
|
}
|
|
97
|
-
// Find index of value with the lastConsumedTimestamp
|
|
98
|
-
let i = values.length - 2;
|
|
99
|
-
while (i >= 0 && values[i].timestamp > data.lastConsumedTimestamp)
|
|
100
|
-
i--;
|
|
101
|
-
// Mark the following value index as the starting point to trigger all the new value callbacks
|
|
102
|
-
startIndex = i + 1;
|
|
103
201
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
case 1 /* TriggerAreaEventType.TAET_STAY */:
|
|
115
|
-
if (!data.triggerCallbackMap.has(1 /* TriggerAreaEventType.TAET_STAY */))
|
|
116
|
-
continue;
|
|
117
|
-
data.triggerCallbackMap.get(1 /* TriggerAreaEventType.TAET_STAY */)(values[i]);
|
|
118
|
-
break;
|
|
119
|
-
case 2 /* TriggerAreaEventType.TAET_EXIT */:
|
|
120
|
-
if (!data.triggerCallbackMap.has(2 /* TriggerAreaEventType.TAET_EXIT */))
|
|
121
|
-
continue;
|
|
122
|
-
data.triggerCallbackMap.get(2 /* TriggerAreaEventType.TAET_EXIT */)(values[i]);
|
|
123
|
-
break;
|
|
202
|
+
// -----------------------------------------------------------------------
|
|
203
|
+
// Pass 2: synthesize per-tick onStay callbacks
|
|
204
|
+
// -----------------------------------------------------------------------
|
|
205
|
+
// Only run if an onStay callback is registered and there are tracked triggerers.
|
|
206
|
+
if (data.triggerCallbackMap.has(1 /* TriggerAreaEventType.TAET_STAY */) &&
|
|
207
|
+
data.insideTriggerers.size > 0) {
|
|
208
|
+
const onStay = data.triggerCallbackMap.get(1 /* TriggerAreaEventType.TAET_STAY */);
|
|
209
|
+
const currentTimestamp = Date.now();
|
|
210
|
+
for (const [triggererEntity, cachedResult] of data.insideTriggerers) {
|
|
211
|
+
onStay(buildSyntheticStayResult(cachedResult, entity, triggererEntity, currentTimestamp, Transform));
|
|
124
212
|
}
|
|
125
213
|
}
|
|
126
|
-
data.lastConsumedTimestamp = values[values.length - 1].timestamp;
|
|
127
214
|
}
|
|
128
|
-
// Clean up garbage entries
|
|
215
|
+
// Clean up garbage entries.
|
|
129
216
|
garbageEntries.forEach((garbageEntity) => entitiesMap.delete(garbageEntity));
|
|
130
217
|
});
|
|
131
218
|
return {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dcl/ecs",
|
|
3
3
|
"description": "Decentraland ECS",
|
|
4
|
-
"version": "7.23.2
|
|
4
|
+
"version": "7.23.2",
|
|
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": "15e86977205ad099c6c1b81f6c14e1acb7b52bd7"
|
|
38
38
|
}
|