@dcl/ecs 7.0.6-3823801200.commit-32470bd → 7.0.6-3830539086.commit-6152fbd

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,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 { CRDTMessageType, ProcessMessageResultType } from '@dcl/crdt/dist/types';
3
+ import { EntityState, EntityUtils } from '../../engine/entity';
2
4
  import { createByteBuffer } from '../../serialization/ByteBuffer';
3
- import { ComponentOperation as Message } from '../../serialization/crdt/componentOperation';
4
- import WireMessage from '../../serialization/wireMessage';
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.
@@ -27,21 +35,47 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
27
35
  const buffer = createByteBuffer({
28
36
  reading: { buffer: chunkMessage, currentOffset: 0 }
29
37
  });
30
- while (WireMessage.validate(buffer)) {
38
+ let header;
39
+ while ((header = CrdtMessageProtocol.getHeader(buffer))) {
31
40
  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
- });
41
+ if (header.type === CrdtMessageType.DELETE_COMPONENT) {
42
+ const message = DeleteComponent.read(buffer);
43
+ receivedMessages.push({
44
+ ...header,
45
+ ...message,
46
+ transportId,
47
+ messageBuffer: buffer
48
+ .buffer()
49
+ .subarray(offset, buffer.currentReadOffset())
50
+ });
51
+ }
52
+ else if (header.type === CrdtMessageType.PUT_COMPONENT) {
53
+ const message = PutComponentOperation.read(buffer);
54
+ receivedMessages.push({
55
+ ...header,
56
+ ...message,
57
+ transportId,
58
+ messageBuffer: buffer
59
+ .buffer()
60
+ .subarray(offset, buffer.currentReadOffset())
61
+ });
62
+ }
63
+ else if (header.type === CrdtMessageType.DELETE_ENTITY) {
64
+ const message = DeleteEntity.read(buffer);
65
+ receivedMessages.push({
66
+ ...header,
67
+ ...message,
68
+ transportId,
69
+ messageBuffer: buffer
70
+ .buffer()
71
+ .subarray(offset, buffer.currentReadOffset())
72
+ });
73
+ // Unknown message, we skip it
74
+ }
75
+ else {
76
+ // consume the message
77
+ buffer.incrementReadOffset(header.length);
78
+ }
45
79
  }
46
80
  // TODO: do something if buffler.len>0
47
81
  };
@@ -61,54 +95,109 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
61
95
  async function receiveMessages() {
62
96
  const messagesToProcess = getMessages(receivedMessages);
63
97
  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())
98
+ const entitiesShouldBeCleaned = [];
99
+ for (const msg of messagesToProcess) {
100
+ // TODO: emit delete entity to el onCrdtMessage
101
+ if (msg.type === CrdtMessageType.DELETE_ENTITY) {
102
+ crdtClient.processMessage({
103
+ type: CRDTMessageType.CRDTMT_DeleteEntity,
104
+ entityId: msg.entityId
93
105
  });
106
+ entitiesShouldBeCleaned.push(msg.entityId);
94
107
  }
95
108
  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);
109
+ // TODO: emit pu/delete component to el onCrdtMessage
110
+ const crdtMessage = {
111
+ type: CRDTMessageType.CRDTMT_PutComponentData,
112
+ entityId: msg.entityId,
113
+ componentId: msg.componentId,
114
+ data: msg.type === CrdtMessageType.PUT_COMPONENT ? msg.data : null,
115
+ timestamp: msg.timestamp
116
+ };
117
+ const entityState = engine.entityContainer.getEntityState(msg.entityId);
118
+ // Skip updates from removed entityes
119
+ if (entityState === EntityState.Removed)
120
+ continue;
121
+ // Entities with unknown entities should update its entity state
122
+ if (entityState === EntityState.Unknown) {
123
+ engine.entityContainer.updateUsedEntity(msg.entityId);
101
124
  }
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);
125
+ const component = engine.getComponentOrNull(msg.componentId);
126
+ // The state isn't updated because the dirty was set
127
+ // out of the block of systems update between `receiveMessage` and `updateState`
128
+ if (component?.isDirty(msg.entityId)) {
129
+ crdtClient.createComponentDataEvent(component._id, msg.entityId, component.toBinaryOrNull(msg.entityId)?.toBinary() || null);
130
+ }
131
+ const processResult = crdtClient.processMessage(crdtMessage);
132
+ if (!component) {
133
+ continue;
134
+ }
135
+ switch (processResult) {
136
+ case ProcessMessageResultType.StateUpdatedTimestamp:
137
+ case ProcessMessageResultType.StateUpdatedData:
138
+ // Add message to transport queue to be processed by others transports
139
+ broadcastMessages.push(msg);
140
+ // Process CRDT Message
141
+ if (msg.type === CrdtMessageType.DELETE_COMPONENT) {
142
+ component.deleteFrom(msg.entityId, false);
143
+ }
144
+ else {
145
+ const opts = {
146
+ reading: { buffer: msg.data, currentOffset: 0 }
147
+ };
148
+ const data = createByteBuffer(opts);
149
+ component.upsertFromBinary(msg.entityId, data, false);
150
+ }
151
+ onProcessEntityComponentChange &&
152
+ onProcessEntityComponentChange(msg.entityId, msg.type, component);
153
+ break;
154
+ // CRDT outdated message. Resend this message to the transport
155
+ // To do this we add this message to a queue that will be processed at the end of the update tick
156
+ case ProcessMessageResultType.StateOutdatedData:
157
+ case ProcessMessageResultType.StateOutdatedTimestamp:
158
+ const current = crdtClient
159
+ .getState()
160
+ .components.get(msg.componentId)
161
+ ?.get(msg.entityId);
162
+ if (current) {
163
+ const offset = bufferForOutdated.currentWriteOffset();
164
+ const ts = current.timestamp;
165
+ if (component.has(msg.entityId)) {
166
+ PutComponentOperation.write(msg.entityId, ts, component, bufferForOutdated);
167
+ }
168
+ else {
169
+ DeleteComponent.write(msg.entityId, component._id, ts, bufferForOutdated);
170
+ }
171
+ outdatedMessages.push({
172
+ ...msg,
173
+ messageBuffer: bufferForOutdated
174
+ .buffer()
175
+ .subarray(offset, bufferForOutdated.currentWriteOffset())
176
+ });
177
+ }
178
+ break;
179
+ case ProcessMessageResultType.NoChanges:
180
+ case ProcessMessageResultType.EntityDeleted:
181
+ case ProcessMessageResultType.EntityWasDeleted:
182
+ default:
183
+ break;
184
+ }
185
+ }
186
+ }
187
+ // TODO: emit delete entity to el onCrdtMessage
188
+ for (const entity of entitiesShouldBeCleaned) {
189
+ // If we tried to resend outdated message and the entity was deleted before, we avoid sending them.
190
+ for (let i = outdatedMessages.length - 1; i >= 0; i--) {
191
+ if (outdatedMessages[i].entityId === entity) {
192
+ outdatedMessages.splice(i, 1);
108
193
  }
109
- onProcessEntityComponentChange &&
110
- onProcessEntityComponentChange(entity, component, type);
111
194
  }
195
+ for (const definition of engine.componentsIter()) {
196
+ definition.deleteFrom(entity, false);
197
+ }
198
+ engine.entityContainer.updateRemovedEntity(entity);
199
+ onProcessEntityComponentChange &&
200
+ onProcessEntityComponentChange(entity, CrdtMessageType.DELETE_ENTITY);
112
201
  }
113
202
  }
114
203
  /**
@@ -126,15 +215,20 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
126
215
  entitySet = [];
127
216
  dirtyMap.set(component, entitySet);
128
217
  }
129
- entitySet.push(entity);
130
218
  // TODO: reuse shared writer to prevent extra allocations of toBinary
131
219
  const componentValue = component.toBinaryOrNull(entity)?.toBinary() ?? null;
132
220
  // 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);
221
+ // if update goes bad, the entity doesn't accept put anymore (it's added to deleted entities set)
222
+ if (crdtClient.createComponentDataEvent(component._id, entity, componentValue) === null) {
223
+ component.deleteFrom(entity, false);
224
+ }
225
+ else {
226
+ entitySet.push(entity);
227
+ onProcessEntityComponentChange &&
228
+ onProcessEntityComponentChange(entity, componentValue === null
229
+ ? CrdtMessageType.DELETE_COMPONENT
230
+ : CrdtMessageType.PUT_COMPONENT, component);
231
+ }
138
232
  }
139
233
  }
140
234
  return dirtyMap;
@@ -142,7 +236,7 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
142
236
  /**
143
237
  * Iterates the dirty map and generates crdt messages to be send
144
238
  */
145
- async function sendMessages(dirtyEntities) {
239
+ async function sendMessages(dirtyEntities, deletedEntities) {
146
240
  // CRDT Messages will be the merge between the recieved transport messages and the new crdt messages
147
241
  const crdtMessages = getMessages(broadcastMessages);
148
242
  const outdatedMessagesBkp = getMessages(outdatedMessages);
@@ -152,19 +246,26 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
152
246
  // Component will be always defined here since dirtyMap its an iterator of engine.componentsDefinition
153
247
  const { timestamp } = crdtClient
154
248
  .getState()
155
- .get(entity)
156
- .get(component._id);
249
+ .components.get(component._id)
250
+ .get(entity);
157
251
  const offset = buffer.currentWriteOffset();
158
- const type = WireMessage.getType(component, entity);
252
+ const type = component.has(entity)
253
+ ? CrdtMessageType.PUT_COMPONENT
254
+ : CrdtMessageType.DELETE_COMPONENT;
159
255
  const transportMessage = {
160
256
  type,
257
+ entityId: entity,
161
258
  componentId: component._id,
162
- entity,
163
259
  timestamp
164
260
  };
165
261
  // Avoid creating messages if there is no transport that will handle it
166
262
  if (transports.some((t) => t.filter(transportMessage))) {
167
- Message.write(type, entity, timestamp, component, buffer);
263
+ if (transportMessage.type === CrdtMessageType.PUT_COMPONENT) {
264
+ PutComponentOperation.write(entity, timestamp, component, buffer);
265
+ }
266
+ else {
267
+ DeleteComponent.write(entity, component._id, timestamp, buffer);
268
+ }
168
269
  crdtMessages.push({
169
270
  ...transportMessage,
170
271
  messageBuffer: buffer
@@ -174,6 +275,19 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
174
275
  }
175
276
  }
176
277
  }
278
+ // After all updates, I execute the DeletedEntity messages
279
+ for (const entityId of deletedEntities) {
280
+ crdtClient.createDeleteEntityEvent(entityId);
281
+ const offset = buffer.currentWriteOffset();
282
+ DeleteEntity.write(entityId, buffer);
283
+ crdtMessages.push({
284
+ type: CrdtMessageType.DELETE_ENTITY,
285
+ entityId,
286
+ messageBuffer: buffer
287
+ .buffer()
288
+ .subarray(offset, buffer.currentWriteOffset())
289
+ });
290
+ }
177
291
  // Send CRDT messages to transports
178
292
  const transportBuffer = createByteBuffer();
179
293
  for (const index in transports) {
@@ -184,8 +298,11 @@ export function crdtSceneSystem(engine, onProcessEntityComponentChange) {
184
298
  // So we can fix their crdt state
185
299
  for (const message of outdatedMessagesBkp) {
186
300
  if (message.transportId === transportIndex &&
301
+ // TODO: This is an optimization, the state should converge anyway, whatever the message is sent.
187
302
  // Avoid sending multiple messages for the same entity-componentId
188
- !crdtMessages.find((m) => m.entity === message.entity &&
303
+ !crdtMessages.find((m) => m.entityId === message.entityId &&
304
+ // TODO: as any, with multiple type of messages, it should have many checks before the check for similar messages
305
+ m.componentId &&
189
306
  m.componentId === message.componentId)) {
190
307
  transportBuffer.writeBuffer(message.messageBuffer, false);
191
308
  }
@@ -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-3823801200.commit-32470bd",
3
+ "version": "7.0.6-3830539086.commit-6152fbd",
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-3823801200.commit-32470bd",
30
+ "@dcl/crdt": "7.0.6-3830539086.commit-6152fbd",
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": "32470bdb44a9d3c8663f432e0d3262a09c4201cf"
44
+ "commit": "6152fbdf7dfabf5e0d61ef713e75e670ed3d69b8"
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 = {}));
@@ -1,41 +0,0 @@
1
- /**
2
- * The wire message is the top-level message that can be packed
3
- * inside it can contain a data with another structure or protocol
4
- *
5
- * Each wire message has three primitive property that it'll never change
6
- * ---> length uint32 (message size up to 4,294,967,295)
7
- * ---> version uint32 (for now just a number which is zero)
8
- * ---> message type uint32
9
- * The length indicates how many bytes are above self, the version in
10
- * combination with message type defines the set of handlers that will be
11
- * available to process the message
12
- *
13
- */
14
- import { ComponentDefinition, Entity } from '../engine';
15
- import { ByteBuffer } from './ByteBuffer';
16
- export declare namespace WireMessage {
17
- type Uint32 = number;
18
- enum Enum {
19
- RESERVED = 0,
20
- PUT_COMPONENT = 1,
21
- DELETE_COMPONENT = 2,
22
- MAX_MESSAGE_TYPE = 3
23
- }
24
- /**
25
- * @param length - Uint32 the length of all message (including the header)
26
- * @param type - define the function which handles the data
27
- */
28
- type Header = {
29
- length: Uint32;
30
- type: Uint32;
31
- };
32
- const HEADER_LENGTH = 8;
33
- /**
34
- * Validate if the message incoming is completed
35
- * @param buf - ByteBuffer
36
- */
37
- function validate(buf: ByteBuffer): boolean;
38
- function readHeader(buf: ByteBuffer): Header | null;
39
- function getType(component: ComponentDefinition<unknown>, entity: Entity): Enum;
40
- }
41
- export default WireMessage;
@@ -1,56 +0,0 @@
1
- /**
2
- * The wire message is the top-level message that can be packed
3
- * inside it can contain a data with another structure or protocol
4
- *
5
- * Each wire message has three primitive property that it'll never change
6
- * ---> length uint32 (message size up to 4,294,967,295)
7
- * ---> version uint32 (for now just a number which is zero)
8
- * ---> message type uint32
9
- * The length indicates how many bytes are above self, the version in
10
- * combination with message type defines the set of handlers that will be
11
- * available to process the message
12
- *
13
- */
14
- export var WireMessage;
15
- (function (WireMessage) {
16
- let Enum;
17
- (function (Enum) {
18
- Enum[Enum["RESERVED"] = 0] = "RESERVED";
19
- // Component Operation
20
- Enum[Enum["PUT_COMPONENT"] = 1] = "PUT_COMPONENT";
21
- Enum[Enum["DELETE_COMPONENT"] = 2] = "DELETE_COMPONENT";
22
- Enum[Enum["MAX_MESSAGE_TYPE"] = 3] = "MAX_MESSAGE_TYPE";
23
- })(Enum = WireMessage.Enum || (WireMessage.Enum = {}));
24
- WireMessage.HEADER_LENGTH = 8;
25
- /**
26
- * Validate if the message incoming is completed
27
- * @param buf - ByteBuffer
28
- */
29
- function validate(buf) {
30
- const rem = buf.remainingBytes();
31
- if (rem < WireMessage.HEADER_LENGTH) {
32
- return false;
33
- }
34
- const messageLength = buf.getUint32(buf.currentReadOffset());
35
- if (rem < messageLength) {
36
- return false;
37
- }
38
- return true;
39
- }
40
- WireMessage.validate = validate;
41
- function readHeader(buf) {
42
- if (!validate(buf)) {
43
- return null;
44
- }
45
- return {
46
- length: buf.readUint32(),
47
- type: buf.readUint32()
48
- };
49
- }
50
- WireMessage.readHeader = readHeader;
51
- function getType(component, entity) {
52
- return component.has(entity) ? Enum.PUT_COMPONENT : Enum.DELETE_COMPONENT;
53
- }
54
- WireMessage.getType = getType;
55
- })(WireMessage || (WireMessage = {}));
56
- export default WireMessage;