@dcl/ecs 7.0.6-3824930139.commit-9bd6c05 → 7.0.6-3832097301.commit-4e46b20

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.
@@ -0,0 +1,13 @@
1
+ import { ComponentDefinition } from '../../engine/component';
2
+ import { Entity } from '../../engine/entity';
3
+ import { ByteBuffer } from '../ByteBuffer';
4
+ import { PutComponentMessage } from './types';
5
+ export declare namespace PutComponentOperation {
6
+ const MESSAGE_HEADER_LENGTH = 20;
7
+ /**
8
+ * Call this function for an optimal writing data passing the ByteBuffer
9
+ * already allocated
10
+ */
11
+ function write(entity: Entity, timestamp: number, componentDefinition: ComponentDefinition<unknown>, buf: ByteBuffer): void;
12
+ function read(buf: ByteBuffer): PutComponentMessage | null;
13
+ }
@@ -0,0 +1,44 @@
1
+ import CrdtMessageProtocol from '.';
2
+ import { CrdtMessageType, CRDT_MESSAGE_HEADER_LENGTH } from './types';
3
+ export var PutComponentOperation;
4
+ (function (PutComponentOperation) {
5
+ PutComponentOperation.MESSAGE_HEADER_LENGTH = 20;
6
+ /**
7
+ * Call this function for an optimal writing data passing the ByteBuffer
8
+ * already allocated
9
+ */
10
+ function write(entity, timestamp, componentDefinition, buf) {
11
+ // reserve the beginning
12
+ const startMessageOffset = buf.incrementWriteOffset(CRDT_MESSAGE_HEADER_LENGTH + PutComponentOperation.MESSAGE_HEADER_LENGTH);
13
+ // write body
14
+ componentDefinition.writeToByteBuffer(entity, buf);
15
+ const messageLength = buf.currentWriteOffset() - startMessageOffset;
16
+ // Write CrdtMessage header
17
+ buf.setUint32(startMessageOffset, messageLength);
18
+ buf.setUint32(startMessageOffset + 4, CrdtMessageType.PUT_COMPONENT);
19
+ // Write ComponentOperation header
20
+ buf.setUint32(startMessageOffset + 8, entity);
21
+ buf.setUint32(startMessageOffset + 12, componentDefinition._id);
22
+ buf.setUint64(startMessageOffset + 16, BigInt(timestamp));
23
+ const newLocal = messageLength - PutComponentOperation.MESSAGE_HEADER_LENGTH - CRDT_MESSAGE_HEADER_LENGTH;
24
+ buf.setUint32(startMessageOffset + 24, newLocal);
25
+ }
26
+ PutComponentOperation.write = write;
27
+ function read(buf) {
28
+ const header = CrdtMessageProtocol.readHeader(buf);
29
+ if (!header) {
30
+ return null;
31
+ }
32
+ if (header.type !== CrdtMessageType.PUT_COMPONENT) {
33
+ throw new Error('PutComponentOperation tried to read another message type.');
34
+ }
35
+ return {
36
+ ...header,
37
+ entityId: buf.readUint32(),
38
+ componentId: buf.readInt32(),
39
+ timestamp: Number(buf.readUint64()),
40
+ data: buf.readBuffer()
41
+ };
42
+ }
43
+ PutComponentOperation.read = read;
44
+ })(PutComponentOperation || (PutComponentOperation = {}));
@@ -0,0 +1,53 @@
1
+ import { Entity } from '../../engine/entity';
2
+ export declare type Uint32 = number;
3
+ export declare enum CrdtMessageType {
4
+ RESERVED = 0,
5
+ PUT_COMPONENT = 1,
6
+ DELETE_COMPONENT = 2,
7
+ DELETE_ENTITY = 3,
8
+ MAX_MESSAGE_TYPE = 4
9
+ }
10
+ /**
11
+ * Min length = 8 bytes
12
+ * All message length including
13
+ * @param length - Uint32 the length of all message (including the header)
14
+ * @param type - define the function which handles the data
15
+ */
16
+ export declare type CrdtMessageHeader = {
17
+ length: Uint32;
18
+ type: Uint32;
19
+ };
20
+ export declare const CRDT_MESSAGE_HEADER_LENGTH = 8;
21
+ /**
22
+ * Min. length = header (8 bytes) + 20 bytes = 28 bytes
23
+ *
24
+ * @param entity - Uint32 number of the entity
25
+ * @param componentId - Uint32 number of id
26
+ * @param timestamp - Uint64 Lamport timestamp
27
+ * @param data - Uint8[] data of component => length(4 bytes) + block of bytes[0..length-1]
28
+ */
29
+ export declare type PutComponentMessageBody = {
30
+ type: CrdtMessageType.PUT_COMPONENT;
31
+ entityId: Entity;
32
+ componentId: number;
33
+ timestamp: number;
34
+ data: Uint8Array;
35
+ };
36
+ export declare type DeleteComponentMessageBody = {
37
+ type: CrdtMessageType.DELETE_COMPONENT;
38
+ entityId: Entity;
39
+ componentId: number;
40
+ timestamp: number;
41
+ };
42
+ /**
43
+ * @param entity - Uint32 number of the entity
44
+ */
45
+ export declare type DeleteEntityMessageBody = {
46
+ type: CrdtMessageType.DELETE_ENTITY;
47
+ entityId: Entity;
48
+ };
49
+ export declare type PutComponentMessage = CrdtMessageHeader & PutComponentMessageBody;
50
+ export declare type DeleteComponentMessage = CrdtMessageHeader & DeleteComponentMessageBody;
51
+ export declare type DeleteEntityMessage = CrdtMessageHeader & DeleteEntityMessageBody;
52
+ export declare type CrdtMessage = PutComponentMessage | DeleteComponentMessage | DeleteEntityMessage;
53
+ export declare type CrdtMessageBody = PutComponentMessageBody | DeleteComponentMessageBody | DeleteEntityMessage;
@@ -0,0 +1,10 @@
1
+ export var CrdtMessageType;
2
+ (function (CrdtMessageType) {
3
+ CrdtMessageType[CrdtMessageType["RESERVED"] = 0] = "RESERVED";
4
+ // Component Operation
5
+ CrdtMessageType[CrdtMessageType["PUT_COMPONENT"] = 1] = "PUT_COMPONENT";
6
+ CrdtMessageType[CrdtMessageType["DELETE_COMPONENT"] = 2] = "DELETE_COMPONENT";
7
+ CrdtMessageType[CrdtMessageType["DELETE_ENTITY"] = 3] = "DELETE_ENTITY";
8
+ CrdtMessageType[CrdtMessageType["MAX_MESSAGE_TYPE"] = 4] = "MAX_MESSAGE_TYPE";
9
+ })(CrdtMessageType || (CrdtMessageType = {}));
10
+ export const CRDT_MESSAGE_HEADER_LENGTH = 8;
@@ -1,14 +1,14 @@
1
- import type { ComponentDefinition, IEngine } from '../../engine';
2
1
  import { Entity } from '../../engine/entity';
3
- import WireMessage from '../../serialization/wireMessage';
2
+ import type { ComponentDefinition, IEngine } from '../../engine';
3
+ import { CrdtMessageType } from '../../serialization/crdt/types';
4
4
  import { Transport } from './types';
5
5
  /**
6
6
  * @public
7
7
  */
8
- export declare type OnChangeFunction = (entity: Entity, component: ComponentDefinition<any>, operation: WireMessage.Enum) => void;
9
- export declare function crdtSceneSystem(engine: Pick<IEngine, 'getComponentOrNull' | 'getComponent' | 'componentsIter'>, onProcessEntityComponentChange: OnChangeFunction | null): {
8
+ export declare type OnChangeFunction = (entity: Entity, operation: CrdtMessageType, component?: ComponentDefinition<any>) => void;
9
+ export declare function crdtSceneSystem(engine: Pick<IEngine, 'getComponentOrNull' | 'getComponent' | 'entityContainer' | 'componentsIter'>, onProcessEntityComponentChange: OnChangeFunction | null): {
10
10
  getCrdt: () => import("@dcl/crdt").State<Uint8Array>;
11
- sendMessages: (dirtyEntities: Map<ComponentDefinition<unknown>, Array<Entity>>) => Promise<void>;
11
+ sendMessages: (dirtyEntities: Map<ComponentDefinition<unknown>, Array<Entity>>, deletedEntities: Entity[]) => Promise<void>;
12
12
  receiveMessages: () => Promise<void>;
13
13
  addTransport: (transport: Transport) => void;
14
14
  updateState: () => Map<ComponentDefinition<unknown>, Entity[]>;
@@ -1,11 +1,19 @@
1
1
  import { crdtProtocol } from '@dcl/crdt';
2
- import { createByteBuffer } from '../../serialization/ByteBuffer';
3
- import { ComponentOperation as Message } from '../../serialization/crdt/componentOperation';
4
- import WireMessage from '../../serialization/wireMessage';
2
+ import { CRDTMessageType, ProcessMessageResultType } from '@dcl/crdt/dist/types';
3
+ import { EntityState, EntityUtils } from '../../engine/entity';
4
+ import { ReadWriteByteBuffer } from '../../serialization/ByteBuffer';
5
+ import CrdtMessageProtocol from '../../serialization/crdt';
6
+ import { DeleteComponent } from '../../serialization/crdt/deleteComponent';
7
+ import { DeleteEntity } from '../../serialization/crdt/deleteEntity';
8
+ import { PutComponentOperation } from '../../serialization/crdt/putComponent';
9
+ import { CrdtMessageType } from '../../serialization/crdt/types';
5
10
  export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
6
11
  const transports = [];
7
12
  // CRDT Client
8
- const crdtClient = crdtProtocol();
13
+ const crdtClient = crdtProtocol({
14
+ toEntityId: EntityUtils.toEntityId,
15
+ fromEntityId: EntityUtils.fromEntityId
16
+ });
9
17
  // Messages that we received at transport.onMessage waiting to be processed
10
18
  const receivedMessages = [];
11
19
  // Messages already processed by the engine but that we need to broadcast to other transports.
@@ -24,24 +32,48 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
24
32
  * @param chunkMessage A chunk of binary messages
25
33
  */
26
34
  return function parseChunkMessage(chunkMessage) {
27
- const buffer = createByteBuffer({
28
- reading: { buffer: chunkMessage, currentOffset: 0 }
29
- });
30
- while (WireMessage.validate(buffer)) {
35
+ const buffer = new ReadWriteByteBuffer(chunkMessage);
36
+ let header;
37
+ while ((header = CrdtMessageProtocol.getHeader(buffer))) {
31
38
  const offset = buffer.currentReadOffset();
32
- const message = Message.read(buffer);
33
- const { type, entity, componentId, data, timestamp } = message;
34
- receivedMessages.push({
35
- type,
36
- entity,
37
- componentId,
38
- data,
39
- timestamp,
40
- transportId,
41
- messageBuffer: buffer
42
- .buffer()
43
- .subarray(offset, buffer.currentReadOffset())
44
- });
39
+ if (header.type === CrdtMessageType.DELETE_COMPONENT) {
40
+ const message = DeleteComponent.read(buffer);
41
+ receivedMessages.push({
42
+ ...header,
43
+ ...message,
44
+ transportId,
45
+ messageBuffer: buffer
46
+ .buffer()
47
+ .subarray(offset, buffer.currentReadOffset())
48
+ });
49
+ }
50
+ else if (header.type === CrdtMessageType.PUT_COMPONENT) {
51
+ const message = PutComponentOperation.read(buffer);
52
+ receivedMessages.push({
53
+ ...header,
54
+ ...message,
55
+ transportId,
56
+ messageBuffer: buffer
57
+ .buffer()
58
+ .subarray(offset, buffer.currentReadOffset())
59
+ });
60
+ }
61
+ else if (header.type === CrdtMessageType.DELETE_ENTITY) {
62
+ const message = DeleteEntity.read(buffer);
63
+ receivedMessages.push({
64
+ ...header,
65
+ ...message,
66
+ transportId,
67
+ messageBuffer: buffer
68
+ .buffer()
69
+ .subarray(offset, buffer.currentReadOffset())
70
+ });
71
+ // Unknown message, we skip it
72
+ }
73
+ else {
74
+ // consume the message
75
+ buffer.incrementReadOffset(header.length);
76
+ }
45
77
  }
46
78
  // TODO: do something if buffler.len>0
47
79
  };
@@ -60,56 +92,105 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
60
92
  */
61
93
  async function receiveMessages() {
62
94
  const messagesToProcess = getMessages(receivedMessages);
63
- const bufferForOutdated = createByteBuffer();
64
- for (const message of messagesToProcess) {
65
- const { data, timestamp, componentId, entity, type } = message;
66
- const crdtMessage = {
67
- key1: entity,
68
- key2: componentId,
69
- data: data || null,
70
- timestamp: timestamp
71
- };
72
- const component = engine.getComponentOrNull(componentId);
73
- if (component?.isDirty(entity)) {
74
- crdtClient.createEvent(entity, component._id, component.toBinaryOrNull(entity)?.toBinary() || null);
75
- }
76
- const current = crdtClient.processMessage(crdtMessage);
77
- if (!component) {
78
- continue;
79
- }
80
- // CRDT outdated message. Resend this message to the transport
81
- // To do this we add this message to a queue that will be processed at the end of the update tick
82
- if (crdtMessage !== current) {
83
- const offset = bufferForOutdated.currentWriteOffset();
84
- const type = WireMessage.getType(component, entity);
85
- const ts = current.timestamp;
86
- Message.write(type, entity, ts, component, bufferForOutdated);
87
- outdatedMessages.push({
88
- ...message,
89
- timestamp: current.timestamp,
90
- messageBuffer: bufferForOutdated
91
- .buffer()
92
- .subarray(offset, bufferForOutdated.currentWriteOffset())
95
+ const bufferForOutdated = new ReadWriteByteBuffer();
96
+ const entitiesShouldBeCleaned = [];
97
+ for (const msg of messagesToProcess) {
98
+ if (msg.type === CrdtMessageType.DELETE_ENTITY) {
99
+ crdtClient.processMessage({
100
+ type: CRDTMessageType.CRDTMT_DeleteEntity,
101
+ entityId: msg.entityId
93
102
  });
103
+ entitiesShouldBeCleaned.push(msg.entityId);
94
104
  }
95
105
  else {
96
- // Add message to transport queue to be processed by others transports
97
- broadcastMessages.push(message);
98
- // Process CRDT Message
99
- if (type === WireMessage.Enum.DELETE_COMPONENT) {
100
- component.deleteFrom(entity, false);
106
+ const crdtMessage = {
107
+ type: CRDTMessageType.CRDTMT_PutComponentData,
108
+ entityId: msg.entityId,
109
+ componentId: msg.componentId,
110
+ data: msg.type === CrdtMessageType.PUT_COMPONENT ? msg.data : null,
111
+ timestamp: msg.timestamp
112
+ };
113
+ const entityState = engine.entityContainer.getEntityState(msg.entityId);
114
+ // Skip updates from removed entityes
115
+ if (entityState === EntityState.Removed)
116
+ continue;
117
+ // Entities with unknown entities should update its entity state
118
+ if (entityState === EntityState.Unknown) {
119
+ engine.entityContainer.updateUsedEntity(msg.entityId);
101
120
  }
102
- else {
103
- const opts = {
104
- reading: { buffer: message.data, currentOffset: 0 }
105
- };
106
- const data = createByteBuffer(opts);
107
- component.upsertFromBinary(message.entity, data, false);
121
+ const component = engine.getComponentOrNull(msg.componentId);
122
+ // The state isn't updated because the dirty was set
123
+ // out of the block of systems update between `receiveMessage` and `updateState`
124
+ if (component?.isDirty(msg.entityId)) {
125
+ crdtClient.createComponentDataEvent(component._id, msg.entityId, component.toBinaryOrNull(msg.entityId)?.toBinary() || null);
126
+ }
127
+ const processResult = crdtClient.processMessage(crdtMessage);
128
+ if (!component) {
129
+ continue;
130
+ }
131
+ switch (processResult) {
132
+ case ProcessMessageResultType.StateUpdatedTimestamp:
133
+ case ProcessMessageResultType.StateUpdatedData:
134
+ // Add message to transport queue to be processed by others transports
135
+ broadcastMessages.push(msg);
136
+ // Process CRDT Message
137
+ if (msg.type === CrdtMessageType.DELETE_COMPONENT) {
138
+ component.deleteFrom(msg.entityId, false);
139
+ }
140
+ else {
141
+ const data = new ReadWriteByteBuffer(msg.data);
142
+ component.upsertFromBinary(msg.entityId, data, false);
143
+ }
144
+ onProcessEntityComponentChange &&
145
+ onProcessEntityComponentChange(msg.entityId, msg.type, component);
146
+ break;
147
+ // CRDT outdated message. Resend this message to the transport
148
+ // To do this we add this message to a queue that will be processed at the end of the update tick
149
+ case ProcessMessageResultType.StateOutdatedData:
150
+ case ProcessMessageResultType.StateOutdatedTimestamp:
151
+ const current = crdtClient
152
+ .getState()
153
+ .components.get(msg.componentId)
154
+ ?.get(msg.entityId);
155
+ if (current) {
156
+ const offset = bufferForOutdated.currentWriteOffset();
157
+ const ts = current.timestamp;
158
+ if (component.has(msg.entityId)) {
159
+ PutComponentOperation.write(msg.entityId, ts, component, bufferForOutdated);
160
+ }
161
+ else {
162
+ DeleteComponent.write(msg.entityId, component._id, ts, bufferForOutdated);
163
+ }
164
+ outdatedMessages.push({
165
+ ...msg,
166
+ messageBuffer: bufferForOutdated
167
+ .buffer()
168
+ .subarray(offset, bufferForOutdated.currentWriteOffset())
169
+ });
170
+ }
171
+ break;
172
+ case ProcessMessageResultType.NoChanges:
173
+ case ProcessMessageResultType.EntityDeleted:
174
+ case ProcessMessageResultType.EntityWasDeleted:
175
+ default:
176
+ break;
108
177
  }
109
- onProcessEntityComponentChange &&
110
- onProcessEntityComponentChange(entity, component, type);
111
178
  }
112
179
  }
180
+ for (const entity of entitiesShouldBeCleaned) {
181
+ // If we tried to resend outdated message and the entity was deleted before, we avoid sending them.
182
+ for (let i = outdatedMessages.length - 1; i >= 0; i--) {
183
+ if (outdatedMessages[i].entityId === entity) {
184
+ outdatedMessages.splice(i, 1);
185
+ }
186
+ }
187
+ for (const definition of engine.componentsIter()) {
188
+ definition.deleteFrom(entity, false);
189
+ }
190
+ engine.entityContainer.updateRemovedEntity(entity);
191
+ onProcessEntityComponentChange &&
192
+ onProcessEntityComponentChange(entity, CrdtMessageType.DELETE_ENTITY);
193
+ }
113
194
  }
114
195
  /**
115
196
  * Updates CRDT state of the current engine dirty components
@@ -126,15 +207,20 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
126
207
  entitySet = [];
127
208
  dirtyMap.set(component, entitySet);
128
209
  }
129
- entitySet.push(entity);
130
210
  // TODO: reuse shared writer to prevent extra allocations of toBinary
131
211
  const componentValue = component.toBinaryOrNull(entity)?.toBinary() ?? null;
132
212
  // TODO: do not emit event if componentValue equals the value didn't change
133
- crdtClient.createEvent(entity, component._id, componentValue);
134
- onProcessEntityComponentChange &&
135
- onProcessEntityComponentChange(entity, component, componentValue === null
136
- ? WireMessage.Enum.DELETE_COMPONENT
137
- : WireMessage.Enum.PUT_COMPONENT);
213
+ // if update goes bad, the entity doesn't accept put anymore (it's added to deleted entities set)
214
+ if (crdtClient.createComponentDataEvent(component._id, entity, componentValue) === null) {
215
+ component.deleteFrom(entity, false);
216
+ }
217
+ else {
218
+ entitySet.push(entity);
219
+ onProcessEntityComponentChange &&
220
+ onProcessEntityComponentChange(entity, componentValue === null
221
+ ? CrdtMessageType.DELETE_COMPONENT
222
+ : CrdtMessageType.PUT_COMPONENT, component);
223
+ }
138
224
  }
139
225
  }
140
226
  return dirtyMap;
@@ -142,29 +228,36 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
142
228
  /**
143
229
  * Iterates the dirty map and generates crdt messages to be send
144
230
  */
145
- async function sendMessages(dirtyEntities) {
231
+ async function sendMessages(dirtyEntities, deletedEntities) {
146
232
  // CRDT Messages will be the merge between the recieved transport messages and the new crdt messages
147
233
  const crdtMessages = getMessages(broadcastMessages);
148
234
  const outdatedMessagesBkp = getMessages(outdatedMessages);
149
- const buffer = createByteBuffer();
235
+ const buffer = new ReadWriteByteBuffer();
150
236
  for (const [component, entities] of dirtyEntities) {
151
237
  for (const entity of entities) {
152
238
  // Component will be always defined here since dirtyMap its an iterator of engine.componentsDefinition
153
239
  const { timestamp } = crdtClient
154
240
  .getState()
155
- .get(entity)
156
- .get(component._id);
241
+ .components.get(component._id)
242
+ .get(entity);
157
243
  const offset = buffer.currentWriteOffset();
158
- const type = WireMessage.getType(component, entity);
244
+ const type = component.has(entity)
245
+ ? CrdtMessageType.PUT_COMPONENT
246
+ : CrdtMessageType.DELETE_COMPONENT;
159
247
  const transportMessage = {
160
248
  type,
249
+ entityId: entity,
161
250
  componentId: component._id,
162
- entity,
163
251
  timestamp
164
252
  };
165
253
  // Avoid creating messages if there is no transport that will handle it
166
254
  if (transports.some((t) => t.filter(transportMessage))) {
167
- Message.write(type, entity, timestamp, component, buffer);
255
+ if (transportMessage.type === CrdtMessageType.PUT_COMPONENT) {
256
+ PutComponentOperation.write(entity, timestamp, component, buffer);
257
+ }
258
+ else {
259
+ DeleteComponent.write(entity, component._id, timestamp, buffer);
260
+ }
168
261
  crdtMessages.push({
169
262
  ...transportMessage,
170
263
  messageBuffer: buffer
@@ -174,8 +267,21 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
174
267
  }
175
268
  }
176
269
  }
270
+ // After all updates, I execute the DeletedEntity messages
271
+ for (const entityId of deletedEntities) {
272
+ crdtClient.createDeleteEntityEvent(entityId);
273
+ const offset = buffer.currentWriteOffset();
274
+ DeleteEntity.write(entityId, buffer);
275
+ crdtMessages.push({
276
+ type: CrdtMessageType.DELETE_ENTITY,
277
+ entityId,
278
+ messageBuffer: buffer
279
+ .buffer()
280
+ .subarray(offset, buffer.currentWriteOffset())
281
+ });
282
+ }
177
283
  // Send CRDT messages to transports
178
- const transportBuffer = createByteBuffer();
284
+ const transportBuffer = new ReadWriteByteBuffer();
179
285
  for (const index in transports) {
180
286
  const transportIndex = Number(index);
181
287
  const transport = transports[transportIndex];
@@ -184,8 +290,11 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
184
290
  // So we can fix their crdt state
185
291
  for (const message of outdatedMessagesBkp) {
186
292
  if (message.transportId === transportIndex &&
293
+ // TODO: This is an optimization, the state should converge anyway, whatever the message is sent.
187
294
  // Avoid sending multiple messages for the same entity-componentId
188
- !crdtMessages.find((m) => m.entity === message.entity &&
295
+ !crdtMessages.find((m) => m.entityId === message.entityId &&
296
+ // TODO: as any, with multiple type of messages, it should have many checks before the check for similar messages
297
+ m.componentId &&
189
298
  m.componentId === message.componentId)) {
190
299
  transportBuffer.writeBuffer(message.messageBuffer, false);
191
300
  }
@@ -197,7 +306,7 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
197
306
  transportBuffer.writeBuffer(message.messageBuffer, false);
198
307
  }
199
308
  }
200
- const message = transportBuffer.size()
309
+ const message = transportBuffer.currentWriteOffset()
201
310
  ? transportBuffer.toBinary()
202
311
  : new Uint8Array([]);
203
312
  await transport.send(message);
@@ -1,12 +1,6 @@
1
- import { Entity } from '../../engine/entity';
2
- import WireMessage from '../../serialization/wireMessage';
3
- export declare type ReceiveMessage = {
4
- type: WireMessage.Enum;
5
- entity: Entity;
6
- componentId: number;
7
- timestamp: number;
1
+ import { CrdtMessageBody } from '../../serialization/crdt/types';
2
+ export declare type ReceiveMessage = CrdtMessageBody & {
8
3
  transportId?: number;
9
- data?: Uint8Array;
10
4
  messageBuffer: Uint8Array;
11
5
  };
12
6
  export declare type TransportMessage = Omit<ReceiveMessage, 'data'>;
@@ -1,4 +1,5 @@
1
1
  import * as components from '../components';
2
+ import { EntityState } from '../engine/entity';
2
3
  import { checkNotThenable } from '../runtime/invariant';
3
4
  export function createPointerEventSystem(engine, inputSystem) {
4
5
  const PointerEvents = components.PointerEvents(engine);
@@ -53,7 +54,7 @@ export function createPointerEventSystem(engine, inputSystem) {
53
54
  // @internal
54
55
  engine.addSystem(function EventSystem() {
55
56
  for (const [entity, event] of eventsMap) {
56
- if (!engine.entityExists(entity)) {
57
+ if (engine.getEntityState(entity) === EntityState.Removed) {
57
58
  eventsMap.delete(entity);
58
59
  continue;
59
60
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcl/ecs",
3
- "version": "7.0.6-3824930139.commit-9bd6c05",
3
+ "version": "7.0.6-3832097301.commit-4e46b20",
4
4
  "description": "Decentraland ECS",
5
5
  "main": "./dist/index.js",
6
6
  "typings": "./dist/index.d.ts",
@@ -27,7 +27,7 @@
27
27
  "ts-proto": "^1.112.0"
28
28
  },
29
29
  "dependencies": {
30
- "@dcl/crdt": "7.0.6-3824930139.commit-9bd6c05",
30
+ "@dcl/crdt": "7.0.6-3832097301.commit-4e46b20",
31
31
  "@dcl/js-runtime": "file:../js-runtime",
32
32
  "@dcl/protocol": "^1.0.0-3808528053.commit-d66d462"
33
33
  },
@@ -41,5 +41,5 @@
41
41
  "displayName": "ECS",
42
42
  "tsconfig": "./tsconfig.json"
43
43
  },
44
- "commit": "9bd6c05a1f07792c260e0c18fb198de3eb530dcf"
44
+ "commit": "4e46b208355a0a0d340a899c44f98bebb94d0c8b"
45
45
  }
@@ -1,31 +0,0 @@
1
- import { ComponentDefinition } from '../../engine/component';
2
- import { Entity } from '../../engine/entity';
3
- import { ByteBuffer } from '../ByteBuffer';
4
- import WireMessage from '../wireMessage';
5
- export declare namespace ComponentOperation {
6
- /**
7
- * @param entity - Uint32 number of the entity
8
- * @param componentId - Uint32 number of id
9
- * @param timestamp - Uint64 Lamport timestamp
10
- * @param data - Uint8[] data of component
11
- */
12
- type IPutComponent = {
13
- entity: Entity;
14
- componentId: number;
15
- timestamp: number;
16
- data: Uint8Array;
17
- };
18
- type IDeleteComponent = {
19
- entity: Entity;
20
- componentId: number;
21
- timestamp: number;
22
- data?: undefined;
23
- };
24
- const MESSAGE_HEADER_LENGTH = 20;
25
- /**
26
- * Call this function for an optimal writing data passing the ByteBuffer
27
- * already allocated
28
- */
29
- function write(type: WireMessage.Enum, entity: Entity, timestamp: number, componentDefinition: ComponentDefinition<unknown>, buf: ByteBuffer): void;
30
- function read(buf: ByteBuffer): (WireMessage.Header & (IPutComponent | IDeleteComponent)) | null;
31
- }
@@ -1,47 +0,0 @@
1
- import WireMessage from '../wireMessage';
2
- export var ComponentOperation;
3
- (function (ComponentOperation) {
4
- ComponentOperation.MESSAGE_HEADER_LENGTH = 20;
5
- /**
6
- * Call this function for an optimal writing data passing the ByteBuffer
7
- * already allocated
8
- */
9
- function write(type, entity, timestamp, componentDefinition, buf) {
10
- // reserve the beginning
11
- const startMessageOffset = buf.incrementWriteOffset(WireMessage.HEADER_LENGTH + ComponentOperation.MESSAGE_HEADER_LENGTH);
12
- // write body
13
- if (type === WireMessage.Enum.PUT_COMPONENT) {
14
- componentDefinition.writeToByteBuffer(entity, buf);
15
- }
16
- const messageLength = buf.size() - startMessageOffset;
17
- // Write WireMessage header
18
- buf.setUint32(startMessageOffset, messageLength);
19
- buf.setUint32(startMessageOffset + 4, type);
20
- // Write ComponentOperation header
21
- buf.setUint32(startMessageOffset + 8, entity);
22
- buf.setUint32(startMessageOffset + 12, componentDefinition._id);
23
- buf.setUint64(startMessageOffset + 16, BigInt(timestamp));
24
- buf.setUint32(startMessageOffset + 24, messageLength - ComponentOperation.MESSAGE_HEADER_LENGTH - WireMessage.HEADER_LENGTH);
25
- }
26
- ComponentOperation.write = write;
27
- function read(buf) {
28
- const header = WireMessage.readHeader(buf);
29
- if (!header) {
30
- return null;
31
- }
32
- const common = {
33
- ...header,
34
- entity: buf.readUint32(),
35
- componentId: buf.readInt32(),
36
- timestamp: Number(buf.readUint64())
37
- };
38
- if (header.type === WireMessage.Enum.DELETE_COMPONENT) {
39
- return common;
40
- }
41
- return {
42
- ...common,
43
- data: buf.readBuffer()
44
- };
45
- }
46
- ComponentOperation.read = read;
47
- })(ComponentOperation || (ComponentOperation = {}));