@dcl/playground-assets 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.
- package/dist/alpha.d.ts +162 -42
- package/dist/beta.d.ts +162 -42
- package/dist/index.bundled.d.ts +162 -42
- package/dist/index.js +776 -291
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/playground/sdk/dcl-sdk.package.json +2 -2
- package/dist/playground-assets.d.ts +162 -42
- package/etc/playground-assets.api.json +1607 -430
- package/etc/playground-assets.api.md +166 -45
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -13130,6 +13130,80 @@
|
|
|
13130
13130
|
|
|
13131
13131
|
var dist = {};
|
|
13132
13132
|
|
|
13133
|
+
var gset = {};
|
|
13134
|
+
|
|
13135
|
+
var hasRequiredGset;
|
|
13136
|
+
|
|
13137
|
+
function requireGset () {
|
|
13138
|
+
if (hasRequiredGset) return gset;
|
|
13139
|
+
hasRequiredGset = 1;
|
|
13140
|
+
Object.defineProperty(gset, "__esModule", { value: true });
|
|
13141
|
+
gset.createGSet = void 0;
|
|
13142
|
+
/**
|
|
13143
|
+
*
|
|
13144
|
+
* @returns a new GSet
|
|
13145
|
+
*/
|
|
13146
|
+
function createGSet() {
|
|
13147
|
+
const lastVersion = new Map();
|
|
13148
|
+
return {
|
|
13149
|
+
/**
|
|
13150
|
+
*
|
|
13151
|
+
* @param n
|
|
13152
|
+
* @param v
|
|
13153
|
+
* @returns
|
|
13154
|
+
*/
|
|
13155
|
+
addTo(n, v) {
|
|
13156
|
+
if (v < 0) {
|
|
13157
|
+
return false;
|
|
13158
|
+
}
|
|
13159
|
+
const currentValue = lastVersion.get(n);
|
|
13160
|
+
// If the version is >=, it means the value it's already in the set
|
|
13161
|
+
if (currentValue !== undefined && currentValue >= v) {
|
|
13162
|
+
return true;
|
|
13163
|
+
}
|
|
13164
|
+
lastVersion.set(n, v);
|
|
13165
|
+
return true;
|
|
13166
|
+
},
|
|
13167
|
+
/**
|
|
13168
|
+
* @returns the set with [number, version] of each value
|
|
13169
|
+
*/
|
|
13170
|
+
get() {
|
|
13171
|
+
const arr = [];
|
|
13172
|
+
for (const [n, v] of lastVersion) {
|
|
13173
|
+
for (let i = 0; i <= v; i++) {
|
|
13174
|
+
arr.push([n, i]);
|
|
13175
|
+
}
|
|
13176
|
+
}
|
|
13177
|
+
return arr;
|
|
13178
|
+
},
|
|
13179
|
+
/**
|
|
13180
|
+
* @returns the set with [number, version] of each value
|
|
13181
|
+
*/
|
|
13182
|
+
has(n, v) {
|
|
13183
|
+
const currentValue = lastVersion.get(n);
|
|
13184
|
+
// If the version is >=, it means the value it's already in the set
|
|
13185
|
+
if (currentValue !== undefined && currentValue >= v) {
|
|
13186
|
+
return true;
|
|
13187
|
+
}
|
|
13188
|
+
return false;
|
|
13189
|
+
},
|
|
13190
|
+
/**
|
|
13191
|
+
* Warning: this function returns the reference to the internal map,
|
|
13192
|
+
* if you need to mutate some value, make a copy.
|
|
13193
|
+
* For optimization purpose the copy isn't made here.
|
|
13194
|
+
*
|
|
13195
|
+
* @returns the map of number to version
|
|
13196
|
+
*/
|
|
13197
|
+
getMap() {
|
|
13198
|
+
return lastVersion;
|
|
13199
|
+
}
|
|
13200
|
+
};
|
|
13201
|
+
}
|
|
13202
|
+
gset.createGSet = createGSet;
|
|
13203
|
+
|
|
13204
|
+
return gset;
|
|
13205
|
+
}
|
|
13206
|
+
|
|
13133
13207
|
var types = {};
|
|
13134
13208
|
|
|
13135
13209
|
var hasRequiredTypes;
|
|
@@ -13137,8 +13211,71 @@
|
|
|
13137
13211
|
function requireTypes () {
|
|
13138
13212
|
if (hasRequiredTypes) return types;
|
|
13139
13213
|
hasRequiredTypes = 1;
|
|
13140
|
-
|
|
13141
|
-
|
|
13214
|
+
(function (exports) {
|
|
13215
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13216
|
+
exports.ProcessMessageResultType = exports.CRDTMessageType = void 0;
|
|
13217
|
+
(function (CRDTMessageType) {
|
|
13218
|
+
CRDTMessageType[CRDTMessageType["CRDTMT_PutComponentData"] = 1] = "CRDTMT_PutComponentData";
|
|
13219
|
+
CRDTMessageType[CRDTMessageType["CRDTMT_DeleteEntity"] = 2] = "CRDTMT_DeleteEntity";
|
|
13220
|
+
})(exports.CRDTMessageType || (exports.CRDTMessageType = {}));
|
|
13221
|
+
(function (ProcessMessageResultType) {
|
|
13222
|
+
/**
|
|
13223
|
+
* Typical message and new state set.
|
|
13224
|
+
* @state CHANGE
|
|
13225
|
+
* @reason Incoming message has a timestamp greater
|
|
13226
|
+
*/
|
|
13227
|
+
ProcessMessageResultType[ProcessMessageResultType["StateUpdatedTimestamp"] = 1] = "StateUpdatedTimestamp";
|
|
13228
|
+
/**
|
|
13229
|
+
* Typical message when it is considered old.
|
|
13230
|
+
* @state it does NOT CHANGE.
|
|
13231
|
+
* @reason incoming message has a timestamp lower.
|
|
13232
|
+
*/
|
|
13233
|
+
ProcessMessageResultType[ProcessMessageResultType["StateOutdatedTimestamp"] = 2] = "StateOutdatedTimestamp";
|
|
13234
|
+
/**
|
|
13235
|
+
* Weird message, same timestamp and data.
|
|
13236
|
+
* @state it does NOT CHANGE.
|
|
13237
|
+
* @reason consistent state between peers.
|
|
13238
|
+
*/
|
|
13239
|
+
ProcessMessageResultType[ProcessMessageResultType["NoChanges"] = 3] = "NoChanges";
|
|
13240
|
+
/**
|
|
13241
|
+
* Less but typical message, same timestamp, resolution by data.
|
|
13242
|
+
* @state it does NOT CHANGE.
|
|
13243
|
+
* @reason incoming message has a LOWER data.
|
|
13244
|
+
*/
|
|
13245
|
+
ProcessMessageResultType[ProcessMessageResultType["StateOutdatedData"] = 4] = "StateOutdatedData";
|
|
13246
|
+
/**
|
|
13247
|
+
* Less but typical message, same timestamp, resolution by data.
|
|
13248
|
+
* @state CHANGE.
|
|
13249
|
+
* @reason incoming message has a GREATER data.
|
|
13250
|
+
*/
|
|
13251
|
+
ProcessMessageResultType[ProcessMessageResultType["StateUpdatedData"] = 5] = "StateUpdatedData";
|
|
13252
|
+
/**
|
|
13253
|
+
* Entity was previously deleted.
|
|
13254
|
+
* @state it does NOT CHANGE.
|
|
13255
|
+
* @reason The message is considered old.
|
|
13256
|
+
*/
|
|
13257
|
+
ProcessMessageResultType[ProcessMessageResultType["EntityWasDeleted"] = 6] = "EntityWasDeleted";
|
|
13258
|
+
/**
|
|
13259
|
+
* Entity should be deleted.
|
|
13260
|
+
* @state CHANGE.
|
|
13261
|
+
* @reason the state is storing old entities
|
|
13262
|
+
*/
|
|
13263
|
+
ProcessMessageResultType[ProcessMessageResultType["EntityDeleted"] = 7] = "EntityDeleted";
|
|
13264
|
+
})(exports.ProcessMessageResultType || (exports.ProcessMessageResultType = {}));
|
|
13265
|
+
// we receive LWW, v=6, we have v=5 => we receive with delay the deleteEntity(v=5)
|
|
13266
|
+
// => we should generate the deleteEntity message effects internally with deleteEntity(v=5),
|
|
13267
|
+
// but don't resend the deleteEntity
|
|
13268
|
+
// - (CRDT) addDeletedEntitySet v=5 (with crdt state cleaning) and then LWW v=6
|
|
13269
|
+
// - (engine) engine.deleteEntity v=5
|
|
13270
|
+
// we receive LWW, v=7, we have v=5 => we receive with delay the deleteEntity(v=5), deleteEntity(v=6), ..., N
|
|
13271
|
+
// => we should generate the deleteEntity message effects internally with deleteEntity(v=5),
|
|
13272
|
+
// but don't resend the deleteEntity
|
|
13273
|
+
// - (CRDT) addDeletedEntitySet v=5 (with crdt state cleaning) and then LWW v=6
|
|
13274
|
+
// - (engine) engine.deleteEntity v=5
|
|
13275
|
+
// msg delete entity: it only should be sent by deleter
|
|
13276
|
+
//
|
|
13277
|
+
|
|
13278
|
+
} (types));
|
|
13142
13279
|
return types;
|
|
13143
13280
|
}
|
|
13144
13281
|
|
|
@@ -13163,46 +13300,57 @@
|
|
|
13163
13300
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
13164
13301
|
};
|
|
13165
13302
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13166
|
-
exports.crdtProtocol = exports.stateIterator = exports.
|
|
13167
|
-
|
|
13303
|
+
exports.crdtProtocol = exports.stateIterator = exports.dataCompare = void 0;
|
|
13304
|
+
const gset_1 = requireGset();
|
|
13305
|
+
const types_1 = requireTypes();
|
|
13168
13306
|
const globalBuffer = globalThis.Buffer;
|
|
13307
|
+
__exportStar(requireTypes(), exports);
|
|
13169
13308
|
/**
|
|
13170
13309
|
* Compare raw data.
|
|
13171
13310
|
* @internal
|
|
13311
|
+
* @returns 0 if is the same data, 1 if a > b, -1 if b > a
|
|
13172
13312
|
*/
|
|
13173
|
-
function
|
|
13313
|
+
function dataCompare(a, b) {
|
|
13174
13314
|
// At reference level
|
|
13175
13315
|
if (a === b)
|
|
13176
|
-
return
|
|
13316
|
+
return 0;
|
|
13317
|
+
if (a === null && b !== null)
|
|
13318
|
+
return -1;
|
|
13319
|
+
if (a !== null && b === null)
|
|
13320
|
+
return 1;
|
|
13177
13321
|
if (a instanceof Uint8Array && b instanceof Uint8Array) {
|
|
13178
|
-
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
|
|
13182
|
-
if (
|
|
13183
|
-
return
|
|
13322
|
+
let res;
|
|
13323
|
+
const n = a.byteLength > b.byteLength ? b.byteLength : a.byteLength;
|
|
13324
|
+
for (let i = 0; i < n; i++) {
|
|
13325
|
+
res = a[i] - b[i];
|
|
13326
|
+
if (res !== 0) {
|
|
13327
|
+
return res > 0 ? 1 : -1;
|
|
13184
13328
|
}
|
|
13185
13329
|
}
|
|
13186
|
-
|
|
13330
|
+
res = a.byteLength - b.byteLength;
|
|
13331
|
+
return res > 0 ? 1 : res < 0 ? -1 : 0;
|
|
13187
13332
|
}
|
|
13188
13333
|
if (globalBuffer) {
|
|
13189
13334
|
/* istanbul ignore next */
|
|
13190
13335
|
if (a instanceof globalBuffer && b instanceof globalBuffer) {
|
|
13191
13336
|
/* istanbul ignore next */
|
|
13192
|
-
return a.
|
|
13337
|
+
return a.compare(b);
|
|
13193
13338
|
}
|
|
13194
13339
|
}
|
|
13195
|
-
|
|
13340
|
+
if (typeof a === 'string') {
|
|
13341
|
+
return a.localeCompare(b);
|
|
13342
|
+
}
|
|
13343
|
+
return a > b ? 1 : -1;
|
|
13196
13344
|
}
|
|
13197
|
-
exports.
|
|
13345
|
+
exports.dataCompare = dataCompare;
|
|
13198
13346
|
/**
|
|
13199
13347
|
* State iterator
|
|
13200
13348
|
* @internal
|
|
13201
13349
|
*/
|
|
13202
13350
|
function* stateIterator(state) {
|
|
13203
|
-
for (const [
|
|
13204
|
-
for (const [
|
|
13205
|
-
yield [
|
|
13351
|
+
for (const [componentId, value1] of state.components.entries()) {
|
|
13352
|
+
for (const [entityId, value2] of value1.entries()) {
|
|
13353
|
+
yield [componentId, entityId, value2];
|
|
13206
13354
|
}
|
|
13207
13355
|
}
|
|
13208
13356
|
}
|
|
@@ -13214,40 +13362,70 @@
|
|
|
13214
13362
|
* to process and store the new data in case its an update, or
|
|
13215
13363
|
* to discard and send our local value cause remote it's outdated.
|
|
13216
13364
|
*/
|
|
13217
|
-
function crdtProtocol() {
|
|
13365
|
+
function crdtProtocol(entityUtils) {
|
|
13218
13366
|
/**
|
|
13219
13367
|
* Local state where we store the latest lamport timestamp
|
|
13220
13368
|
* and the raw data value
|
|
13221
13369
|
* @internal
|
|
13222
13370
|
*/
|
|
13223
|
-
const state =
|
|
13371
|
+
const state = {
|
|
13372
|
+
components: new Map(),
|
|
13373
|
+
deletedEntities: (0, gset_1.createGSet)()
|
|
13374
|
+
};
|
|
13224
13375
|
/**
|
|
13225
13376
|
* We should call this fn in order to update the state
|
|
13226
13377
|
* @internal
|
|
13227
13378
|
*/
|
|
13228
|
-
function updateState(
|
|
13229
|
-
|
|
13230
|
-
const
|
|
13231
|
-
|
|
13232
|
-
|
|
13379
|
+
function updateState(componentId, entityId, // todo: force type entity
|
|
13380
|
+
data, remoteTimestamp) {
|
|
13381
|
+
const componentIdValue = state.components.get(componentId);
|
|
13382
|
+
const timestamp = Math.max(remoteTimestamp, componentIdValue?.get(entityId)?.timestamp || 0);
|
|
13383
|
+
if (componentIdValue) {
|
|
13384
|
+
componentIdValue.set(entityId, { timestamp, data });
|
|
13233
13385
|
}
|
|
13234
13386
|
else {
|
|
13235
|
-
const
|
|
13236
|
-
|
|
13237
|
-
state.set(
|
|
13387
|
+
const componentIdValue = new Map();
|
|
13388
|
+
componentIdValue.set(entityId, { timestamp, data });
|
|
13389
|
+
state.components.set(componentId, componentIdValue);
|
|
13238
13390
|
}
|
|
13239
13391
|
return { timestamp, data };
|
|
13240
13392
|
}
|
|
13241
13393
|
/**
|
|
13242
13394
|
* Create an event for the specified key and store the new data and
|
|
13243
|
-
* lamport timestmap incremented by one in the state.
|
|
13395
|
+
* lamport timestmap incremented by one in the state.components.
|
|
13396
|
+
* @public
|
|
13397
|
+
*/
|
|
13398
|
+
function createComponentDataEvent(componentId, entityId, data) {
|
|
13399
|
+
// Increment the timestamp
|
|
13400
|
+
const timestamp = (state.components.get(componentId)?.get(entityId)?.timestamp || 0) + 1;
|
|
13401
|
+
const msg = {
|
|
13402
|
+
type: types_1.CRDTMessageType.CRDTMT_PutComponentData,
|
|
13403
|
+
componentId,
|
|
13404
|
+
entityId,
|
|
13405
|
+
data,
|
|
13406
|
+
timestamp
|
|
13407
|
+
};
|
|
13408
|
+
const res = processComponentDataMessage(msg);
|
|
13409
|
+
if (res === types_1.ProcessMessageResultType.StateUpdatedTimestamp) {
|
|
13410
|
+
return msg;
|
|
13411
|
+
}
|
|
13412
|
+
else {
|
|
13413
|
+
return null;
|
|
13414
|
+
}
|
|
13415
|
+
}
|
|
13416
|
+
/**
|
|
13417
|
+
* Create an event for the specified key and store the new data and
|
|
13418
|
+
* lamport timestmap incremented by one in the state.components.
|
|
13244
13419
|
* @public
|
|
13245
13420
|
*/
|
|
13246
|
-
function
|
|
13421
|
+
function createDeleteEntityEvent(entityId) {
|
|
13247
13422
|
// Increment the timestamp
|
|
13248
|
-
const
|
|
13249
|
-
|
|
13250
|
-
|
|
13423
|
+
const message = {
|
|
13424
|
+
type: types_1.CRDTMessageType.CRDTMT_DeleteEntity,
|
|
13425
|
+
entityId
|
|
13426
|
+
};
|
|
13427
|
+
processDeleteEntityMessage(message);
|
|
13428
|
+
return message;
|
|
13251
13429
|
}
|
|
13252
13430
|
/**
|
|
13253
13431
|
* Process the received message only if the lamport number recieved is higher
|
|
@@ -13258,42 +13436,59 @@
|
|
|
13258
13436
|
* If it was an outdated message, then we return void
|
|
13259
13437
|
* @public
|
|
13260
13438
|
*/
|
|
13261
|
-
function
|
|
13262
|
-
const
|
|
13263
|
-
|
|
13264
|
-
|
|
13439
|
+
function processComponentDataMessage(message) {
|
|
13440
|
+
const [entityNumber, entityVersion] = entityUtils.fromEntityId(message.entityId);
|
|
13441
|
+
if (state.deletedEntities.has(entityNumber, entityVersion)) {
|
|
13442
|
+
return types_1.ProcessMessageResultType.EntityWasDeleted;
|
|
13443
|
+
}
|
|
13444
|
+
const { componentId, entityId, data, timestamp } = message;
|
|
13445
|
+
const current = state.components.get(componentId)?.get(entityId);
|
|
13446
|
+
// The received message is > than our current value, update our state.components.
|
|
13265
13447
|
if (!current || current.timestamp < timestamp) {
|
|
13266
|
-
updateState(
|
|
13267
|
-
return
|
|
13448
|
+
updateState(componentId, entityId, data, timestamp);
|
|
13449
|
+
return types_1.ProcessMessageResultType.StateUpdatedTimestamp;
|
|
13268
13450
|
}
|
|
13269
13451
|
// Outdated Message. Resend our state message through the wire.
|
|
13270
13452
|
if (current.timestamp > timestamp) {
|
|
13271
|
-
return
|
|
13272
|
-
key1,
|
|
13273
|
-
key2,
|
|
13274
|
-
data: current.data,
|
|
13275
|
-
timestamp: current.timestamp
|
|
13276
|
-
};
|
|
13453
|
+
return types_1.ProcessMessageResultType.StateOutdatedData;
|
|
13277
13454
|
}
|
|
13455
|
+
const currentDataGreater = dataCompare(current.data, data);
|
|
13278
13456
|
// Same data, same timestamp. Weirdo echo message.
|
|
13279
|
-
if (
|
|
13280
|
-
return
|
|
13457
|
+
if (currentDataGreater === 0) {
|
|
13458
|
+
return types_1.ProcessMessageResultType.NoChanges;
|
|
13459
|
+
// Current data is greater
|
|
13281
13460
|
}
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
//
|
|
13285
|
-
return !current || current > data;
|
|
13461
|
+
else if (currentDataGreater > 0) {
|
|
13462
|
+
return types_1.ProcessMessageResultType.StateOutdatedData;
|
|
13463
|
+
// Curent data is lower
|
|
13286
13464
|
}
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
key2,
|
|
13291
|
-
data: current.data,
|
|
13292
|
-
timestamp: current.timestamp
|
|
13293
|
-
};
|
|
13465
|
+
else {
|
|
13466
|
+
updateState(componentId, entityId, data, timestamp);
|
|
13467
|
+
return types_1.ProcessMessageResultType.StateUpdatedData;
|
|
13294
13468
|
}
|
|
13295
|
-
|
|
13296
|
-
|
|
13469
|
+
}
|
|
13470
|
+
/*
|
|
13471
|
+
* @public
|
|
13472
|
+
*/
|
|
13473
|
+
function processMessage(message) {
|
|
13474
|
+
if (message.type === types_1.CRDTMessageType.CRDTMT_PutComponentData) {
|
|
13475
|
+
return processComponentDataMessage(message);
|
|
13476
|
+
}
|
|
13477
|
+
else if (message.type === types_1.CRDTMessageType.CRDTMT_DeleteEntity) {
|
|
13478
|
+
return processDeleteEntityMessage(message);
|
|
13479
|
+
}
|
|
13480
|
+
else {
|
|
13481
|
+
return types_1.ProcessMessageResultType.NoChanges;
|
|
13482
|
+
}
|
|
13483
|
+
}
|
|
13484
|
+
function processDeleteEntityMessage(message) {
|
|
13485
|
+
const { entityId } = message;
|
|
13486
|
+
const [entityNumber, entityVersion] = entityUtils.fromEntityId(message.entityId);
|
|
13487
|
+
state.deletedEntities.addTo(entityNumber, entityVersion);
|
|
13488
|
+
for (const [, payload] of state.components) {
|
|
13489
|
+
payload.delete(entityId);
|
|
13490
|
+
}
|
|
13491
|
+
return types_1.ProcessMessageResultType.EntityDeleted;
|
|
13297
13492
|
}
|
|
13298
13493
|
/**
|
|
13299
13494
|
* Returns the current state
|
|
@@ -13306,12 +13501,13 @@
|
|
|
13306
13501
|
* Returns the element state of a given element of the LWW-ElementSet
|
|
13307
13502
|
* @public
|
|
13308
13503
|
*/
|
|
13309
|
-
function getElementSetState(
|
|
13310
|
-
return state.get(
|
|
13504
|
+
function getElementSetState(componentId, entityId) {
|
|
13505
|
+
return state.components.get(componentId)?.get(entityId) || null;
|
|
13311
13506
|
}
|
|
13312
13507
|
return {
|
|
13313
13508
|
getElementSetState,
|
|
13314
|
-
|
|
13509
|
+
createComponentDataEvent,
|
|
13510
|
+
createDeleteEntityEvent,
|
|
13315
13511
|
processMessage,
|
|
13316
13512
|
getState
|
|
13317
13513
|
};
|
|
@@ -13324,6 +13520,171 @@
|
|
|
13324
13520
|
|
|
13325
13521
|
var distExports = requireDist();
|
|
13326
13522
|
|
|
13523
|
+
var typesExports = requireTypes();
|
|
13524
|
+
|
|
13525
|
+
var gsetExports = requireGset();
|
|
13526
|
+
|
|
13527
|
+
const MAX_U16 = 0xffff;
|
|
13528
|
+
const MASK_UPPER_16_ON_32 = 0xffff0000;
|
|
13529
|
+
const AMOUNT_VERSION_AVAILABLE = MAX_U16 + 1;
|
|
13530
|
+
// This type matches with @dcl/crdt entity type.
|
|
13531
|
+
/**
|
|
13532
|
+
* @public This first 512 entities are reserved by the renderer
|
|
13533
|
+
*/
|
|
13534
|
+
const RESERVED_STATIC_ENTITIES = 512;
|
|
13535
|
+
/**
|
|
13536
|
+
* @public
|
|
13537
|
+
*/
|
|
13538
|
+
const MAX_ENTITY_NUMBER = MAX_U16;
|
|
13539
|
+
exports.EntityUtils = void 0;
|
|
13540
|
+
(function (EntityUtils) {
|
|
13541
|
+
/**
|
|
13542
|
+
* @returns [entityNumber, entityVersion]
|
|
13543
|
+
*/
|
|
13544
|
+
function fromEntityId(entityId) {
|
|
13545
|
+
return [
|
|
13546
|
+
(entityId & MAX_U16) >>> 0,
|
|
13547
|
+
(((entityId & MASK_UPPER_16_ON_32) >> 16) & MAX_U16) >>> 0
|
|
13548
|
+
];
|
|
13549
|
+
}
|
|
13550
|
+
EntityUtils.fromEntityId = fromEntityId;
|
|
13551
|
+
/**
|
|
13552
|
+
* @returns compound number from entityNumber and entityVerison
|
|
13553
|
+
*/
|
|
13554
|
+
function toEntityId(entityNumber, entityVersion) {
|
|
13555
|
+
return (((entityNumber & MAX_U16) | ((entityVersion & MAX_U16) << 16)) >>>
|
|
13556
|
+
0);
|
|
13557
|
+
}
|
|
13558
|
+
EntityUtils.toEntityId = toEntityId;
|
|
13559
|
+
})(exports.EntityUtils || (exports.EntityUtils = {}));
|
|
13560
|
+
/**
|
|
13561
|
+
* @public
|
|
13562
|
+
*/
|
|
13563
|
+
exports.EntityState = void 0;
|
|
13564
|
+
(function (EntityState) {
|
|
13565
|
+
EntityState[EntityState["Unknown"] = 0] = "Unknown";
|
|
13566
|
+
/**
|
|
13567
|
+
* The entity was generated and added to the usedEntities set
|
|
13568
|
+
*/
|
|
13569
|
+
EntityState[EntityState["UsedEntity"] = 1] = "UsedEntity";
|
|
13570
|
+
/**
|
|
13571
|
+
* The entity was removed from current engine or remotely
|
|
13572
|
+
*/
|
|
13573
|
+
EntityState[EntityState["Removed"] = 2] = "Removed";
|
|
13574
|
+
/**
|
|
13575
|
+
* The entity is reserved number.
|
|
13576
|
+
*/
|
|
13577
|
+
EntityState[EntityState["Reserved"] = 3] = "Reserved";
|
|
13578
|
+
})(exports.EntityState || (exports.EntityState = {}));
|
|
13579
|
+
function EntityContainer() {
|
|
13580
|
+
let entityCounter = RESERVED_STATIC_ENTITIES;
|
|
13581
|
+
const usedEntities = new Set();
|
|
13582
|
+
let toRemoveEntities = [];
|
|
13583
|
+
const removedEntities = gsetExports.createGSet();
|
|
13584
|
+
function generateNewEntity() {
|
|
13585
|
+
if (entityCounter > MAX_ENTITY_NUMBER - 1) {
|
|
13586
|
+
throw new Error(`It fails trying to generate an entity out of range ${MAX_ENTITY_NUMBER}.`);
|
|
13587
|
+
}
|
|
13588
|
+
const entityNumber = entityCounter++;
|
|
13589
|
+
const entityVersion = removedEntities.getMap().has(entityNumber)
|
|
13590
|
+
? removedEntities.getMap().get(entityNumber) + 1
|
|
13591
|
+
: 0;
|
|
13592
|
+
const entity = exports.EntityUtils.toEntityId(entityNumber, entityVersion);
|
|
13593
|
+
usedEntities.add(entity);
|
|
13594
|
+
return entity;
|
|
13595
|
+
}
|
|
13596
|
+
function generateEntity() {
|
|
13597
|
+
// If all entities until `entityCounter` are being used, we need to generate another one
|
|
13598
|
+
if (usedEntities.size + RESERVED_STATIC_ENTITIES >= entityCounter) {
|
|
13599
|
+
return generateNewEntity();
|
|
13600
|
+
}
|
|
13601
|
+
for (const [number, version] of removedEntities.getMap()) {
|
|
13602
|
+
if (version < MAX_U16) {
|
|
13603
|
+
const entity = exports.EntityUtils.toEntityId(number, version + 1);
|
|
13604
|
+
// If the entity is not being used, we can re-use it
|
|
13605
|
+
// If the entity was removed in this tick, we're not counting for the usedEntities, but we have it in the toRemoveEntityArray
|
|
13606
|
+
if (!usedEntities.has(entity) && !toRemoveEntities.includes(entity)) {
|
|
13607
|
+
usedEntities.add(entity);
|
|
13608
|
+
return entity;
|
|
13609
|
+
}
|
|
13610
|
+
}
|
|
13611
|
+
}
|
|
13612
|
+
return generateNewEntity();
|
|
13613
|
+
}
|
|
13614
|
+
function removeEntity(entity) {
|
|
13615
|
+
if (entity < RESERVED_STATIC_ENTITIES)
|
|
13616
|
+
return false;
|
|
13617
|
+
if (usedEntities.has(entity)) {
|
|
13618
|
+
usedEntities.delete(entity);
|
|
13619
|
+
toRemoveEntities.push(entity);
|
|
13620
|
+
}
|
|
13621
|
+
else {
|
|
13622
|
+
updateRemovedEntity(entity);
|
|
13623
|
+
}
|
|
13624
|
+
return true;
|
|
13625
|
+
}
|
|
13626
|
+
function releaseRemovedEntities() {
|
|
13627
|
+
const arr = toRemoveEntities;
|
|
13628
|
+
toRemoveEntities = [];
|
|
13629
|
+
for (const entity of arr) {
|
|
13630
|
+
const [n, v] = exports.EntityUtils.fromEntityId(entity);
|
|
13631
|
+
removedEntities.addTo(n, v);
|
|
13632
|
+
}
|
|
13633
|
+
return arr;
|
|
13634
|
+
}
|
|
13635
|
+
function updateRemovedEntity(entity) {
|
|
13636
|
+
const [n, v] = exports.EntityUtils.fromEntityId(entity);
|
|
13637
|
+
// Update the removed entities map
|
|
13638
|
+
removedEntities.addTo(n, v);
|
|
13639
|
+
// Remove the usedEntities if exist
|
|
13640
|
+
for (let i = 0; i <= v; i++) {
|
|
13641
|
+
usedEntities.delete(exports.EntityUtils.toEntityId(n, i));
|
|
13642
|
+
}
|
|
13643
|
+
return true;
|
|
13644
|
+
}
|
|
13645
|
+
function updateUsedEntity(entity) {
|
|
13646
|
+
const [n, v] = exports.EntityUtils.fromEntityId(entity);
|
|
13647
|
+
const removedVersion = removedEntities.getMap().get(n);
|
|
13648
|
+
if (removedVersion !== undefined && removedVersion >= v) {
|
|
13649
|
+
return false;
|
|
13650
|
+
}
|
|
13651
|
+
// Update
|
|
13652
|
+
if (v > 0) {
|
|
13653
|
+
for (let i = 0; i <= v - 1; i++) {
|
|
13654
|
+
usedEntities.delete(exports.EntityUtils.toEntityId(n, i));
|
|
13655
|
+
}
|
|
13656
|
+
removedEntities.addTo(n, v - 1);
|
|
13657
|
+
}
|
|
13658
|
+
usedEntities.add(entity);
|
|
13659
|
+
return true;
|
|
13660
|
+
}
|
|
13661
|
+
function getEntityState(entity) {
|
|
13662
|
+
const [n, v] = exports.EntityUtils.fromEntityId(entity);
|
|
13663
|
+
if (n < RESERVED_STATIC_ENTITIES) {
|
|
13664
|
+
return exports.EntityState.Reserved;
|
|
13665
|
+
}
|
|
13666
|
+
if (usedEntities.has(entity)) {
|
|
13667
|
+
return exports.EntityState.UsedEntity;
|
|
13668
|
+
}
|
|
13669
|
+
const removedVersion = removedEntities.getMap().get(n);
|
|
13670
|
+
if (removedVersion !== undefined && removedVersion >= v) {
|
|
13671
|
+
return exports.EntityState.Removed;
|
|
13672
|
+
}
|
|
13673
|
+
return exports.EntityState.Unknown;
|
|
13674
|
+
}
|
|
13675
|
+
return {
|
|
13676
|
+
generateEntity,
|
|
13677
|
+
removeEntity,
|
|
13678
|
+
getExistingEntities() {
|
|
13679
|
+
return new Set(usedEntities);
|
|
13680
|
+
},
|
|
13681
|
+
getEntityState,
|
|
13682
|
+
releaseRemovedEntities,
|
|
13683
|
+
updateRemovedEntity,
|
|
13684
|
+
updateUsedEntity
|
|
13685
|
+
};
|
|
13686
|
+
}
|
|
13687
|
+
|
|
13327
13688
|
var utf8Exports = requireUtf8();
|
|
13328
13689
|
|
|
13329
13690
|
/**
|
|
@@ -13583,114 +13944,204 @@
|
|
|
13583
13944
|
};
|
|
13584
13945
|
}
|
|
13585
13946
|
|
|
13586
|
-
|
|
13587
|
-
|
|
13588
|
-
|
|
13589
|
-
|
|
13590
|
-
|
|
13591
|
-
|
|
13592
|
-
|
|
13593
|
-
|
|
13594
|
-
|
|
13595
|
-
|
|
13596
|
-
|
|
13597
|
-
|
|
13598
|
-
|
|
13599
|
-
|
|
13600
|
-
|
|
13601
|
-
|
|
13602
|
-
|
|
13603
|
-
|
|
13604
|
-
|
|
13605
|
-
|
|
13606
|
-
|
|
13607
|
-
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
}
|
|
13619
|
-
const messageLength = buf.getUint32(buf.currentReadOffset());
|
|
13620
|
-
if (rem < messageLength) {
|
|
13621
|
-
return false;
|
|
13622
|
-
}
|
|
13623
|
-
return true;
|
|
13947
|
+
exports.CrdtMessageType = void 0;
|
|
13948
|
+
(function (CrdtMessageType) {
|
|
13949
|
+
CrdtMessageType[CrdtMessageType["RESERVED"] = 0] = "RESERVED";
|
|
13950
|
+
// Component Operation
|
|
13951
|
+
CrdtMessageType[CrdtMessageType["PUT_COMPONENT"] = 1] = "PUT_COMPONENT";
|
|
13952
|
+
CrdtMessageType[CrdtMessageType["DELETE_COMPONENT"] = 2] = "DELETE_COMPONENT";
|
|
13953
|
+
CrdtMessageType[CrdtMessageType["DELETE_ENTITY"] = 3] = "DELETE_ENTITY";
|
|
13954
|
+
CrdtMessageType[CrdtMessageType["MAX_MESSAGE_TYPE"] = 4] = "MAX_MESSAGE_TYPE";
|
|
13955
|
+
})(exports.CrdtMessageType || (exports.CrdtMessageType = {}));
|
|
13956
|
+
const CRDT_MESSAGE_HEADER_LENGTH = 8;
|
|
13957
|
+
|
|
13958
|
+
exports.DeleteComponent = void 0;
|
|
13959
|
+
(function (DeleteComponent) {
|
|
13960
|
+
// TODO: change timestamp to 32 bit and remove buffer length (-8 bytes)
|
|
13961
|
+
DeleteComponent.MESSAGE_HEADER_LENGTH = 20;
|
|
13962
|
+
/**
|
|
13963
|
+
* Write DeleteComponent message
|
|
13964
|
+
*/
|
|
13965
|
+
function write(entity, componentId, timestamp, buf) {
|
|
13966
|
+
// reserve the beginning
|
|
13967
|
+
const messageLength = CRDT_MESSAGE_HEADER_LENGTH + DeleteComponent.MESSAGE_HEADER_LENGTH;
|
|
13968
|
+
const startMessageOffset = buf.incrementWriteOffset(messageLength);
|
|
13969
|
+
// Write CrdtMessage header
|
|
13970
|
+
buf.setUint32(startMessageOffset, messageLength);
|
|
13971
|
+
buf.setUint32(startMessageOffset + 4, exports.CrdtMessageType.DELETE_COMPONENT);
|
|
13972
|
+
// Write ComponentOperation header
|
|
13973
|
+
buf.setUint32(startMessageOffset + 8, entity);
|
|
13974
|
+
buf.setUint32(startMessageOffset + 12, componentId);
|
|
13975
|
+
// TODO: change timestamp to 32bit (-4 bytes)
|
|
13976
|
+
buf.setUint64(startMessageOffset + 16, BigInt(timestamp));
|
|
13977
|
+
// TODO: remove buffer length (-4 bytes)
|
|
13978
|
+
buf.setUint32(startMessageOffset + 24, 0);
|
|
13624
13979
|
}
|
|
13625
|
-
|
|
13626
|
-
function
|
|
13627
|
-
|
|
13980
|
+
DeleteComponent.write = write;
|
|
13981
|
+
function read(buf) {
|
|
13982
|
+
const header = CrdtMessageProtocol.readHeader(buf);
|
|
13983
|
+
if (!header) {
|
|
13628
13984
|
return null;
|
|
13629
13985
|
}
|
|
13630
|
-
|
|
13631
|
-
|
|
13632
|
-
|
|
13986
|
+
if (header.type !== exports.CrdtMessageType.DELETE_COMPONENT) {
|
|
13987
|
+
throw new Error('DeleteComponentOperation tried to read another message type.');
|
|
13988
|
+
}
|
|
13989
|
+
const msg = {
|
|
13990
|
+
...header,
|
|
13991
|
+
entityId: buf.readUint32(),
|
|
13992
|
+
componentId: buf.readInt32(),
|
|
13993
|
+
timestamp: Number(buf.readUint64())
|
|
13633
13994
|
};
|
|
13995
|
+
// TODO: remove buffer length
|
|
13996
|
+
buf.incrementReadOffset(4);
|
|
13997
|
+
return msg;
|
|
13634
13998
|
}
|
|
13635
|
-
|
|
13636
|
-
|
|
13637
|
-
return component.has(entity) ? Enum.PUT_COMPONENT : Enum.DELETE_COMPONENT;
|
|
13638
|
-
}
|
|
13639
|
-
WireMessage.getType = getType;
|
|
13640
|
-
})(WireMessage || (WireMessage = {}));
|
|
13641
|
-
var WireMessage$1 = WireMessage;
|
|
13999
|
+
DeleteComponent.read = read;
|
|
14000
|
+
})(exports.DeleteComponent || (exports.DeleteComponent = {}));
|
|
13642
14001
|
|
|
13643
|
-
|
|
13644
|
-
(function (
|
|
13645
|
-
|
|
14002
|
+
exports.PutComponentOperation = void 0;
|
|
14003
|
+
(function (PutComponentOperation) {
|
|
14004
|
+
PutComponentOperation.MESSAGE_HEADER_LENGTH = 20;
|
|
13646
14005
|
/**
|
|
13647
14006
|
* Call this function for an optimal writing data passing the ByteBuffer
|
|
13648
14007
|
* already allocated
|
|
13649
14008
|
*/
|
|
13650
|
-
function write(
|
|
14009
|
+
function write(entity, timestamp, componentDefinition, buf) {
|
|
13651
14010
|
// reserve the beginning
|
|
13652
|
-
const startMessageOffset = buf.incrementWriteOffset(
|
|
14011
|
+
const startMessageOffset = buf.incrementWriteOffset(CRDT_MESSAGE_HEADER_LENGTH + PutComponentOperation.MESSAGE_HEADER_LENGTH);
|
|
13653
14012
|
// write body
|
|
13654
|
-
|
|
13655
|
-
componentDefinition.writeToByteBuffer(entity, buf);
|
|
13656
|
-
}
|
|
14013
|
+
componentDefinition.writeToByteBuffer(entity, buf);
|
|
13657
14014
|
const messageLength = buf.size() - startMessageOffset;
|
|
13658
|
-
// Write
|
|
14015
|
+
// Write CrdtMessage header
|
|
13659
14016
|
buf.setUint32(startMessageOffset, messageLength);
|
|
13660
|
-
buf.setUint32(startMessageOffset + 4,
|
|
14017
|
+
buf.setUint32(startMessageOffset + 4, exports.CrdtMessageType.PUT_COMPONENT);
|
|
13661
14018
|
// Write ComponentOperation header
|
|
13662
14019
|
buf.setUint32(startMessageOffset + 8, entity);
|
|
13663
14020
|
buf.setUint32(startMessageOffset + 12, componentDefinition._id);
|
|
13664
14021
|
buf.setUint64(startMessageOffset + 16, BigInt(timestamp));
|
|
13665
|
-
|
|
14022
|
+
const newLocal = messageLength - PutComponentOperation.MESSAGE_HEADER_LENGTH - CRDT_MESSAGE_HEADER_LENGTH;
|
|
14023
|
+
buf.setUint32(startMessageOffset + 24, newLocal);
|
|
13666
14024
|
}
|
|
13667
|
-
|
|
14025
|
+
PutComponentOperation.write = write;
|
|
13668
14026
|
function read(buf) {
|
|
13669
|
-
const header =
|
|
14027
|
+
const header = CrdtMessageProtocol.readHeader(buf);
|
|
13670
14028
|
if (!header) {
|
|
13671
14029
|
return null;
|
|
13672
14030
|
}
|
|
13673
|
-
|
|
14031
|
+
if (header.type !== exports.CrdtMessageType.PUT_COMPONENT) {
|
|
14032
|
+
throw new Error('PutComponentOperation tried to read another message type.');
|
|
14033
|
+
}
|
|
14034
|
+
return {
|
|
13674
14035
|
...header,
|
|
13675
|
-
|
|
14036
|
+
entityId: buf.readUint32(),
|
|
13676
14037
|
componentId: buf.readInt32(),
|
|
13677
|
-
timestamp: Number(buf.readUint64())
|
|
14038
|
+
timestamp: Number(buf.readUint64()),
|
|
14039
|
+
data: buf.readBuffer()
|
|
13678
14040
|
};
|
|
13679
|
-
|
|
13680
|
-
|
|
14041
|
+
}
|
|
14042
|
+
PutComponentOperation.read = read;
|
|
14043
|
+
})(exports.PutComponentOperation || (exports.PutComponentOperation = {}));
|
|
14044
|
+
|
|
14045
|
+
exports.DeleteEntity = void 0;
|
|
14046
|
+
(function (DeleteEntity) {
|
|
14047
|
+
DeleteEntity.MESSAGE_HEADER_LENGTH = 4;
|
|
14048
|
+
function write(entity, buf) {
|
|
14049
|
+
// Write CrdtMessage header
|
|
14050
|
+
buf.writeUint32(CRDT_MESSAGE_HEADER_LENGTH + 4);
|
|
14051
|
+
buf.writeUint32(exports.CrdtMessageType.DELETE_ENTITY);
|
|
14052
|
+
// body
|
|
14053
|
+
buf.writeUint32(entity);
|
|
14054
|
+
}
|
|
14055
|
+
DeleteEntity.write = write;
|
|
14056
|
+
function read(buf) {
|
|
14057
|
+
const header = CrdtMessageProtocol.readHeader(buf);
|
|
14058
|
+
if (!header) {
|
|
14059
|
+
return null;
|
|
14060
|
+
}
|
|
14061
|
+
if (header.type !== exports.CrdtMessageType.DELETE_ENTITY) {
|
|
14062
|
+
throw new Error('DeleteComponentOperation tried to read another message type.');
|
|
13681
14063
|
}
|
|
13682
14064
|
return {
|
|
13683
|
-
...
|
|
13684
|
-
|
|
14065
|
+
...header,
|
|
14066
|
+
entityId: buf.readUint32()
|
|
14067
|
+
};
|
|
14068
|
+
}
|
|
14069
|
+
DeleteEntity.read = read;
|
|
14070
|
+
})(exports.DeleteEntity || (exports.DeleteEntity = {}));
|
|
14071
|
+
|
|
14072
|
+
exports.CrdtMessageProtocol = void 0;
|
|
14073
|
+
(function (CrdtMessageProtocol) {
|
|
14074
|
+
/**
|
|
14075
|
+
* Validate if the message incoming is completed
|
|
14076
|
+
* @param buf - ByteBuffer
|
|
14077
|
+
*/
|
|
14078
|
+
function validate(buf) {
|
|
14079
|
+
const rem = buf.remainingBytes();
|
|
14080
|
+
if (rem < CRDT_MESSAGE_HEADER_LENGTH) {
|
|
14081
|
+
return false;
|
|
14082
|
+
}
|
|
14083
|
+
const messageLength = buf.getUint32(buf.currentReadOffset());
|
|
14084
|
+
if (rem < messageLength) {
|
|
14085
|
+
return false;
|
|
14086
|
+
}
|
|
14087
|
+
return true;
|
|
14088
|
+
}
|
|
14089
|
+
CrdtMessageProtocol.validate = validate;
|
|
14090
|
+
/**
|
|
14091
|
+
* Get the current header, consuming the bytes involved.
|
|
14092
|
+
* @param buf - ByteBuffer
|
|
14093
|
+
* @returns header or null if there is no validated message
|
|
14094
|
+
*/
|
|
14095
|
+
function readHeader(buf) {
|
|
14096
|
+
if (!validate(buf)) {
|
|
14097
|
+
return null;
|
|
14098
|
+
}
|
|
14099
|
+
return {
|
|
14100
|
+
length: buf.readUint32(),
|
|
14101
|
+
type: buf.readUint32()
|
|
13685
14102
|
};
|
|
13686
14103
|
}
|
|
13687
|
-
|
|
13688
|
-
|
|
14104
|
+
CrdtMessageProtocol.readHeader = readHeader;
|
|
14105
|
+
/**
|
|
14106
|
+
* Get the current header, without consuming the bytes involved.
|
|
14107
|
+
* @param buf - ByteBuffer
|
|
14108
|
+
* @returns header or null if there is no validated message
|
|
14109
|
+
*/
|
|
14110
|
+
function getHeader(buf) {
|
|
14111
|
+
if (!validate(buf)) {
|
|
14112
|
+
return null;
|
|
14113
|
+
}
|
|
14114
|
+
const currentOffset = buf.currentReadOffset();
|
|
14115
|
+
return {
|
|
14116
|
+
length: buf.getUint32(currentOffset),
|
|
14117
|
+
type: buf.getUint32(currentOffset + 4)
|
|
14118
|
+
};
|
|
14119
|
+
}
|
|
14120
|
+
CrdtMessageProtocol.getHeader = getHeader;
|
|
14121
|
+
/**
|
|
14122
|
+
* Consume the incoming message without processing it.
|
|
14123
|
+
* @param buf - ByteBuffer
|
|
14124
|
+
* @returns true in case of success or false if there is no valid message.
|
|
14125
|
+
*/
|
|
14126
|
+
function consumeMessage(buf) {
|
|
14127
|
+
const header = getHeader(buf);
|
|
14128
|
+
if (!header) {
|
|
14129
|
+
return false;
|
|
14130
|
+
}
|
|
14131
|
+
buf.incrementReadOffset(header.length);
|
|
14132
|
+
return true;
|
|
14133
|
+
}
|
|
14134
|
+
CrdtMessageProtocol.consumeMessage = consumeMessage;
|
|
14135
|
+
})(exports.CrdtMessageProtocol || (exports.CrdtMessageProtocol = {}));
|
|
14136
|
+
var CrdtMessageProtocol = exports.CrdtMessageProtocol;
|
|
13689
14137
|
|
|
13690
14138
|
function crdtSceneSystem(engine, onProcessEntityComponentChange) {
|
|
13691
14139
|
const transports = [];
|
|
13692
14140
|
// CRDT Client
|
|
13693
|
-
const crdtClient = distExports.crdtProtocol(
|
|
14141
|
+
const crdtClient = distExports.crdtProtocol({
|
|
14142
|
+
toEntityId: exports.EntityUtils.toEntityId,
|
|
14143
|
+
fromEntityId: exports.EntityUtils.fromEntityId
|
|
14144
|
+
});
|
|
13694
14145
|
// Messages that we received at transport.onMessage waiting to be processed
|
|
13695
14146
|
const receivedMessages = [];
|
|
13696
14147
|
// Messages already processed by the engine but that we need to broadcast to other transports.
|
|
@@ -13712,21 +14163,47 @@
|
|
|
13712
14163
|
const buffer = createByteBuffer({
|
|
13713
14164
|
reading: { buffer: chunkMessage, currentOffset: 0 }
|
|
13714
14165
|
});
|
|
13715
|
-
|
|
14166
|
+
let header;
|
|
14167
|
+
while ((header = CrdtMessageProtocol.getHeader(buffer))) {
|
|
13716
14168
|
const offset = buffer.currentReadOffset();
|
|
13717
|
-
|
|
13718
|
-
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
|
|
13727
|
-
|
|
13728
|
-
|
|
13729
|
-
|
|
14169
|
+
if (header.type === exports.CrdtMessageType.DELETE_COMPONENT) {
|
|
14170
|
+
const message = exports.DeleteComponent.read(buffer);
|
|
14171
|
+
receivedMessages.push({
|
|
14172
|
+
...header,
|
|
14173
|
+
...message,
|
|
14174
|
+
transportId,
|
|
14175
|
+
messageBuffer: buffer
|
|
14176
|
+
.buffer()
|
|
14177
|
+
.subarray(offset, buffer.currentReadOffset())
|
|
14178
|
+
});
|
|
14179
|
+
}
|
|
14180
|
+
else if (header.type === exports.CrdtMessageType.PUT_COMPONENT) {
|
|
14181
|
+
const message = exports.PutComponentOperation.read(buffer);
|
|
14182
|
+
receivedMessages.push({
|
|
14183
|
+
...header,
|
|
14184
|
+
...message,
|
|
14185
|
+
transportId,
|
|
14186
|
+
messageBuffer: buffer
|
|
14187
|
+
.buffer()
|
|
14188
|
+
.subarray(offset, buffer.currentReadOffset())
|
|
14189
|
+
});
|
|
14190
|
+
}
|
|
14191
|
+
else if (header.type === exports.CrdtMessageType.DELETE_ENTITY) {
|
|
14192
|
+
const message = exports.DeleteEntity.read(buffer);
|
|
14193
|
+
receivedMessages.push({
|
|
14194
|
+
...header,
|
|
14195
|
+
...message,
|
|
14196
|
+
transportId,
|
|
14197
|
+
messageBuffer: buffer
|
|
14198
|
+
.buffer()
|
|
14199
|
+
.subarray(offset, buffer.currentReadOffset())
|
|
14200
|
+
});
|
|
14201
|
+
// Unknown message, we skip it
|
|
14202
|
+
}
|
|
14203
|
+
else {
|
|
14204
|
+
// consume the message
|
|
14205
|
+
buffer.incrementReadOffset(header.length);
|
|
14206
|
+
}
|
|
13730
14207
|
}
|
|
13731
14208
|
// TODO: do something if buffler.len>0
|
|
13732
14209
|
};
|
|
@@ -13746,54 +14223,107 @@
|
|
|
13746
14223
|
async function receiveMessages() {
|
|
13747
14224
|
const messagesToProcess = getMessages(receivedMessages);
|
|
13748
14225
|
const bufferForOutdated = createByteBuffer();
|
|
13749
|
-
|
|
13750
|
-
|
|
13751
|
-
|
|
13752
|
-
|
|
13753
|
-
|
|
13754
|
-
|
|
13755
|
-
|
|
13756
|
-
};
|
|
13757
|
-
const component = engine.getComponentOrNull(componentId);
|
|
13758
|
-
if (component?.isDirty(entity)) {
|
|
13759
|
-
crdtClient.createEvent(entity, component._id, component.toBinaryOrNull(entity)?.toBinary() || null);
|
|
13760
|
-
}
|
|
13761
|
-
const current = crdtClient.processMessage(crdtMessage);
|
|
13762
|
-
if (!component) {
|
|
13763
|
-
continue;
|
|
13764
|
-
}
|
|
13765
|
-
// CRDT outdated message. Resend this message to the transport
|
|
13766
|
-
// To do this we add this message to a queue that will be processed at the end of the update tick
|
|
13767
|
-
if (crdtMessage !== current) {
|
|
13768
|
-
const offset = bufferForOutdated.currentWriteOffset();
|
|
13769
|
-
const type = WireMessage$1.getType(component, entity);
|
|
13770
|
-
const ts = current.timestamp;
|
|
13771
|
-
ComponentOperation.write(type, entity, ts, component, bufferForOutdated);
|
|
13772
|
-
outdatedMessages.push({
|
|
13773
|
-
...message,
|
|
13774
|
-
timestamp: current.timestamp,
|
|
13775
|
-
messageBuffer: bufferForOutdated
|
|
13776
|
-
.buffer()
|
|
13777
|
-
.subarray(offset, bufferForOutdated.currentWriteOffset())
|
|
14226
|
+
const entitiesShouldBeCleaned = [];
|
|
14227
|
+
for (const msg of messagesToProcess) {
|
|
14228
|
+
// TODO: emit delete entity to el onCrdtMessage
|
|
14229
|
+
if (msg.type === exports.CrdtMessageType.DELETE_ENTITY) {
|
|
14230
|
+
crdtClient.processMessage({
|
|
14231
|
+
type: typesExports.CRDTMessageType.CRDTMT_DeleteEntity,
|
|
14232
|
+
entityId: msg.entityId
|
|
13778
14233
|
});
|
|
14234
|
+
entitiesShouldBeCleaned.push(msg.entityId);
|
|
13779
14235
|
}
|
|
13780
14236
|
else {
|
|
13781
|
-
//
|
|
13782
|
-
|
|
13783
|
-
|
|
13784
|
-
|
|
13785
|
-
|
|
14237
|
+
// TODO: emit pu/delete component to el onCrdtMessage
|
|
14238
|
+
const crdtMessage = {
|
|
14239
|
+
type: typesExports.CRDTMessageType.CRDTMT_PutComponentData,
|
|
14240
|
+
entityId: msg.entityId,
|
|
14241
|
+
componentId: msg.componentId,
|
|
14242
|
+
data: msg.type === exports.CrdtMessageType.PUT_COMPONENT ? msg.data : null,
|
|
14243
|
+
timestamp: msg.timestamp
|
|
14244
|
+
};
|
|
14245
|
+
const entityState = engine.entityContainer.getEntityState(msg.entityId);
|
|
14246
|
+
// Skip updates from removed entityes
|
|
14247
|
+
if (entityState === exports.EntityState.Removed)
|
|
14248
|
+
continue;
|
|
14249
|
+
// Entities with unknown entities should update its entity state
|
|
14250
|
+
if (entityState === exports.EntityState.Unknown) {
|
|
14251
|
+
engine.entityContainer.updateUsedEntity(msg.entityId);
|
|
13786
14252
|
}
|
|
13787
|
-
|
|
13788
|
-
|
|
13789
|
-
|
|
13790
|
-
|
|
13791
|
-
|
|
13792
|
-
component.upsertFromBinary(message.entity, data, false);
|
|
14253
|
+
const component = engine.getComponentOrNull(msg.componentId);
|
|
14254
|
+
// The state isn't updated because the dirty was set
|
|
14255
|
+
// out of the block of systems update between `receiveMessage` and `updateState`
|
|
14256
|
+
if (component?.isDirty(msg.entityId)) {
|
|
14257
|
+
crdtClient.createComponentDataEvent(component._id, msg.entityId, component.toBinaryOrNull(msg.entityId)?.toBinary() || null);
|
|
13793
14258
|
}
|
|
13794
|
-
|
|
13795
|
-
|
|
14259
|
+
const processResult = crdtClient.processMessage(crdtMessage);
|
|
14260
|
+
if (!component) {
|
|
14261
|
+
continue;
|
|
14262
|
+
}
|
|
14263
|
+
switch (processResult) {
|
|
14264
|
+
case typesExports.ProcessMessageResultType.StateUpdatedTimestamp:
|
|
14265
|
+
case typesExports.ProcessMessageResultType.StateUpdatedData:
|
|
14266
|
+
// Add message to transport queue to be processed by others transports
|
|
14267
|
+
broadcastMessages.push(msg);
|
|
14268
|
+
// Process CRDT Message
|
|
14269
|
+
if (msg.type === exports.CrdtMessageType.DELETE_COMPONENT) {
|
|
14270
|
+
component.deleteFrom(msg.entityId, false);
|
|
14271
|
+
}
|
|
14272
|
+
else {
|
|
14273
|
+
const opts = {
|
|
14274
|
+
reading: { buffer: msg.data, currentOffset: 0 }
|
|
14275
|
+
};
|
|
14276
|
+
const data = createByteBuffer(opts);
|
|
14277
|
+
component.upsertFromBinary(msg.entityId, data, false);
|
|
14278
|
+
}
|
|
14279
|
+
onProcessEntityComponentChange &&
|
|
14280
|
+
onProcessEntityComponentChange(msg.entityId, msg.type, component);
|
|
14281
|
+
break;
|
|
14282
|
+
// CRDT outdated message. Resend this message to the transport
|
|
14283
|
+
// To do this we add this message to a queue that will be processed at the end of the update tick
|
|
14284
|
+
case typesExports.ProcessMessageResultType.StateOutdatedData:
|
|
14285
|
+
case typesExports.ProcessMessageResultType.StateOutdatedTimestamp:
|
|
14286
|
+
const current = crdtClient
|
|
14287
|
+
.getState()
|
|
14288
|
+
.components.get(msg.componentId)
|
|
14289
|
+
?.get(msg.entityId);
|
|
14290
|
+
if (current) {
|
|
14291
|
+
const offset = bufferForOutdated.currentWriteOffset();
|
|
14292
|
+
const ts = current.timestamp;
|
|
14293
|
+
if (component.has(msg.entityId)) {
|
|
14294
|
+
exports.PutComponentOperation.write(msg.entityId, ts, component, bufferForOutdated);
|
|
14295
|
+
}
|
|
14296
|
+
else {
|
|
14297
|
+
exports.DeleteComponent.write(msg.entityId, component._id, ts, bufferForOutdated);
|
|
14298
|
+
}
|
|
14299
|
+
outdatedMessages.push({
|
|
14300
|
+
...msg,
|
|
14301
|
+
messageBuffer: bufferForOutdated
|
|
14302
|
+
.buffer()
|
|
14303
|
+
.subarray(offset, bufferForOutdated.currentWriteOffset())
|
|
14304
|
+
});
|
|
14305
|
+
}
|
|
14306
|
+
break;
|
|
14307
|
+
case typesExports.ProcessMessageResultType.NoChanges:
|
|
14308
|
+
case typesExports.ProcessMessageResultType.EntityDeleted:
|
|
14309
|
+
case typesExports.ProcessMessageResultType.EntityWasDeleted:
|
|
14310
|
+
}
|
|
14311
|
+
}
|
|
14312
|
+
}
|
|
14313
|
+
// TODO: emit delete entity to el onCrdtMessage
|
|
14314
|
+
for (const entity of entitiesShouldBeCleaned) {
|
|
14315
|
+
// If we tried to resend outdated message and the entity was deleted before, we avoid sending them.
|
|
14316
|
+
for (let i = outdatedMessages.length - 1; i >= 0; i--) {
|
|
14317
|
+
if (outdatedMessages[i].entityId === entity) {
|
|
14318
|
+
outdatedMessages.splice(i, 1);
|
|
14319
|
+
}
|
|
14320
|
+
}
|
|
14321
|
+
for (const definition of engine.componentsIter()) {
|
|
14322
|
+
definition.deleteFrom(entity, false);
|
|
13796
14323
|
}
|
|
14324
|
+
engine.entityContainer.updateRemovedEntity(entity);
|
|
14325
|
+
onProcessEntityComponentChange &&
|
|
14326
|
+
onProcessEntityComponentChange(entity, exports.CrdtMessageType.DELETE_ENTITY);
|
|
13797
14327
|
}
|
|
13798
14328
|
}
|
|
13799
14329
|
/**
|
|
@@ -13811,15 +14341,20 @@
|
|
|
13811
14341
|
entitySet = [];
|
|
13812
14342
|
dirtyMap.set(component, entitySet);
|
|
13813
14343
|
}
|
|
13814
|
-
entitySet.push(entity);
|
|
13815
14344
|
// TODO: reuse shared writer to prevent extra allocations of toBinary
|
|
13816
14345
|
const componentValue = component.toBinaryOrNull(entity)?.toBinary() ?? null;
|
|
13817
14346
|
// TODO: do not emit event if componentValue equals the value didn't change
|
|
13818
|
-
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
|
|
13822
|
-
|
|
14347
|
+
// if update goes bad, the entity doesn't accept put anymore (it's added to deleted entities set)
|
|
14348
|
+
if (crdtClient.createComponentDataEvent(component._id, entity, componentValue) === null) {
|
|
14349
|
+
component.deleteFrom(entity, false);
|
|
14350
|
+
}
|
|
14351
|
+
else {
|
|
14352
|
+
entitySet.push(entity);
|
|
14353
|
+
onProcessEntityComponentChange &&
|
|
14354
|
+
onProcessEntityComponentChange(entity, componentValue === null
|
|
14355
|
+
? exports.CrdtMessageType.DELETE_COMPONENT
|
|
14356
|
+
: exports.CrdtMessageType.PUT_COMPONENT, component);
|
|
14357
|
+
}
|
|
13823
14358
|
}
|
|
13824
14359
|
}
|
|
13825
14360
|
return dirtyMap;
|
|
@@ -13827,7 +14362,7 @@
|
|
|
13827
14362
|
/**
|
|
13828
14363
|
* Iterates the dirty map and generates crdt messages to be send
|
|
13829
14364
|
*/
|
|
13830
|
-
async function sendMessages(dirtyEntities) {
|
|
14365
|
+
async function sendMessages(dirtyEntities, deletedEntities) {
|
|
13831
14366
|
// CRDT Messages will be the merge between the recieved transport messages and the new crdt messages
|
|
13832
14367
|
const crdtMessages = getMessages(broadcastMessages);
|
|
13833
14368
|
const outdatedMessagesBkp = getMessages(outdatedMessages);
|
|
@@ -13837,19 +14372,26 @@
|
|
|
13837
14372
|
// Component will be always defined here since dirtyMap its an iterator of engine.componentsDefinition
|
|
13838
14373
|
const { timestamp } = crdtClient
|
|
13839
14374
|
.getState()
|
|
13840
|
-
.get(
|
|
13841
|
-
.get(
|
|
14375
|
+
.components.get(component._id)
|
|
14376
|
+
.get(entity);
|
|
13842
14377
|
const offset = buffer.currentWriteOffset();
|
|
13843
|
-
const type =
|
|
14378
|
+
const type = component.has(entity)
|
|
14379
|
+
? exports.CrdtMessageType.PUT_COMPONENT
|
|
14380
|
+
: exports.CrdtMessageType.DELETE_COMPONENT;
|
|
13844
14381
|
const transportMessage = {
|
|
13845
14382
|
type,
|
|
14383
|
+
entityId: entity,
|
|
13846
14384
|
componentId: component._id,
|
|
13847
|
-
entity,
|
|
13848
14385
|
timestamp
|
|
13849
14386
|
};
|
|
13850
14387
|
// Avoid creating messages if there is no transport that will handle it
|
|
13851
14388
|
if (transports.some((t) => t.filter(transportMessage))) {
|
|
13852
|
-
|
|
14389
|
+
if (transportMessage.type === exports.CrdtMessageType.PUT_COMPONENT) {
|
|
14390
|
+
exports.PutComponentOperation.write(entity, timestamp, component, buffer);
|
|
14391
|
+
}
|
|
14392
|
+
else {
|
|
14393
|
+
exports.DeleteComponent.write(entity, component._id, timestamp, buffer);
|
|
14394
|
+
}
|
|
13853
14395
|
crdtMessages.push({
|
|
13854
14396
|
...transportMessage,
|
|
13855
14397
|
messageBuffer: buffer
|
|
@@ -13859,6 +14401,19 @@
|
|
|
13859
14401
|
}
|
|
13860
14402
|
}
|
|
13861
14403
|
}
|
|
14404
|
+
// After all updates, I execute the DeletedEntity messages
|
|
14405
|
+
for (const entityId of deletedEntities) {
|
|
14406
|
+
crdtClient.createDeleteEntityEvent(entityId);
|
|
14407
|
+
const offset = buffer.currentWriteOffset();
|
|
14408
|
+
exports.DeleteEntity.write(entityId, buffer);
|
|
14409
|
+
crdtMessages.push({
|
|
14410
|
+
type: exports.CrdtMessageType.DELETE_ENTITY,
|
|
14411
|
+
entityId,
|
|
14412
|
+
messageBuffer: buffer
|
|
14413
|
+
.buffer()
|
|
14414
|
+
.subarray(offset, buffer.currentWriteOffset())
|
|
14415
|
+
});
|
|
14416
|
+
}
|
|
13862
14417
|
// Send CRDT messages to transports
|
|
13863
14418
|
const transportBuffer = createByteBuffer();
|
|
13864
14419
|
for (const index in transports) {
|
|
@@ -13869,8 +14424,11 @@
|
|
|
13869
14424
|
// So we can fix their crdt state
|
|
13870
14425
|
for (const message of outdatedMessagesBkp) {
|
|
13871
14426
|
if (message.transportId === transportIndex &&
|
|
14427
|
+
// TODO: This is an optimization, the state should converge anyway, whatever the message is sent.
|
|
13872
14428
|
// Avoid sending multiple messages for the same entity-componentId
|
|
13873
|
-
!crdtMessages.find((m) => m.
|
|
14429
|
+
!crdtMessages.find((m) => m.entityId === message.entityId &&
|
|
14430
|
+
// TODO: as any, with multiple type of messages, it should have many checks before the check for similar messages
|
|
14431
|
+
m.componentId &&
|
|
13874
14432
|
m.componentId === message.componentId)) {
|
|
13875
14433
|
transportBuffer.writeBuffer(message.messageBuffer, false);
|
|
13876
14434
|
}
|
|
@@ -14058,79 +14616,6 @@
|
|
|
14058
14616
|
};
|
|
14059
14617
|
}
|
|
14060
14618
|
|
|
14061
|
-
const MAX_U16 = 0xffff;
|
|
14062
|
-
const MASK_UPPER_16_ON_32 = 0xffff0000;
|
|
14063
|
-
const AMOUNT_VERSION_AVAILABLE = MAX_U16 + 1;
|
|
14064
|
-
/**
|
|
14065
|
-
* @public This first 512 entities are reserved by the renderer
|
|
14066
|
-
*/
|
|
14067
|
-
const RESERVED_STATIC_ENTITIES = 512;
|
|
14068
|
-
/**
|
|
14069
|
-
* @public
|
|
14070
|
-
*/
|
|
14071
|
-
const MAX_ENTITY_NUMBER = MAX_U16;
|
|
14072
|
-
function EntityContainer() {
|
|
14073
|
-
let entityCounter = RESERVED_STATIC_ENTITIES;
|
|
14074
|
-
const usedEntities = new Set();
|
|
14075
|
-
const removedEntities = new Map();
|
|
14076
|
-
function entityVersion(entity) {
|
|
14077
|
-
return (((entity & MASK_UPPER_16_ON_32) >> 16) & MAX_U16) >>> 0;
|
|
14078
|
-
}
|
|
14079
|
-
function entityNumber(entity) {
|
|
14080
|
-
return (entity & MAX_U16) >>> 0;
|
|
14081
|
-
}
|
|
14082
|
-
function entityId(entityNumber, entityVersion) {
|
|
14083
|
-
return (((entityNumber & MAX_U16) | ((entityVersion & MAX_U16) << 16)) >>>
|
|
14084
|
-
0);
|
|
14085
|
-
}
|
|
14086
|
-
function generateNewEntity() {
|
|
14087
|
-
if (entityCounter > MAX_ENTITY_NUMBER - 1) {
|
|
14088
|
-
throw new Error(`It fails trying to generate an entity out of range ${MAX_ENTITY_NUMBER}.`);
|
|
14089
|
-
}
|
|
14090
|
-
const entity = entityCounter++;
|
|
14091
|
-
usedEntities.add(entity);
|
|
14092
|
-
return entity;
|
|
14093
|
-
}
|
|
14094
|
-
function generateEntity() {
|
|
14095
|
-
if (usedEntities.size + RESERVED_STATIC_ENTITIES >= entityCounter) {
|
|
14096
|
-
return generateNewEntity();
|
|
14097
|
-
}
|
|
14098
|
-
for (const [number, version] of removedEntities) {
|
|
14099
|
-
if (version < MAX_U16) {
|
|
14100
|
-
const entity = entityId(number, version + 1);
|
|
14101
|
-
usedEntities.add(entity);
|
|
14102
|
-
removedEntities.delete(number);
|
|
14103
|
-
return entity;
|
|
14104
|
-
}
|
|
14105
|
-
}
|
|
14106
|
-
return generateNewEntity();
|
|
14107
|
-
}
|
|
14108
|
-
function removeEntity(entity) {
|
|
14109
|
-
const deleted = usedEntities.delete(entity);
|
|
14110
|
-
if (deleted) {
|
|
14111
|
-
removedEntities.set(entityNumber(entity), entityVersion(entity));
|
|
14112
|
-
}
|
|
14113
|
-
return deleted;
|
|
14114
|
-
}
|
|
14115
|
-
return {
|
|
14116
|
-
generateEntity() {
|
|
14117
|
-
return generateEntity();
|
|
14118
|
-
},
|
|
14119
|
-
removeEntity(entity) {
|
|
14120
|
-
return removeEntity(entity);
|
|
14121
|
-
},
|
|
14122
|
-
entityExists(entity) {
|
|
14123
|
-
return entity < RESERVED_STATIC_ENTITIES || usedEntities.has(entity);
|
|
14124
|
-
},
|
|
14125
|
-
getExistingEntities() {
|
|
14126
|
-
return new Set(usedEntities);
|
|
14127
|
-
},
|
|
14128
|
-
entityVersion,
|
|
14129
|
-
entityNumber,
|
|
14130
|
-
entityId
|
|
14131
|
-
};
|
|
14132
|
-
}
|
|
14133
|
-
|
|
14134
14619
|
const SYSTEMS_REGULAR_PRIORITY = 100e3;
|
|
14135
14620
|
function SystemContainer() {
|
|
14136
14621
|
const systems = [];
|
|
@@ -14345,9 +14830,6 @@
|
|
|
14345
14830
|
const entity = entityContainer.generateEntity();
|
|
14346
14831
|
return entity;
|
|
14347
14832
|
}
|
|
14348
|
-
function entityExists(entity) {
|
|
14349
|
-
return entityContainer.entityExists(entity);
|
|
14350
|
-
}
|
|
14351
14833
|
function removeEntity(entity) {
|
|
14352
14834
|
for (const [, component] of componentsDefinition) {
|
|
14353
14835
|
if (component.has(entity)) {
|
|
@@ -14454,8 +14936,6 @@
|
|
|
14454
14936
|
}
|
|
14455
14937
|
}
|
|
14456
14938
|
return {
|
|
14457
|
-
entityExists,
|
|
14458
|
-
componentsDefinition,
|
|
14459
14939
|
addEntity,
|
|
14460
14940
|
removeEntity,
|
|
14461
14941
|
addSystem,
|
|
@@ -14469,6 +14949,7 @@
|
|
|
14469
14949
|
removeComponentDefinition,
|
|
14470
14950
|
removeEntityWithChildren,
|
|
14471
14951
|
registerCustomComponent,
|
|
14952
|
+
entityContainer,
|
|
14472
14953
|
componentsIter
|
|
14473
14954
|
};
|
|
14474
14955
|
}
|
|
@@ -14485,8 +14966,9 @@
|
|
|
14485
14966
|
checkNotThenable(ret, `A system (${system.name || 'anonymous'}) returned a thenable. Systems cannot be async functions. Documentation: https://dcl.gg/sdk/sync-systems`);
|
|
14486
14967
|
}
|
|
14487
14968
|
const dirtyEntities = crdtSystem.updateState();
|
|
14488
|
-
|
|
14489
|
-
|
|
14969
|
+
const deletedEntites = engine.entityContainer.releaseRemovedEntities();
|
|
14970
|
+
await crdtSystem.sendMessages(dirtyEntities, deletedEntites);
|
|
14971
|
+
for (const definition of engine.componentsIter()) {
|
|
14490
14972
|
definition.clearDirty();
|
|
14491
14973
|
}
|
|
14492
14974
|
}
|
|
@@ -14508,10 +14990,10 @@
|
|
|
14508
14990
|
RootEntity: 0,
|
|
14509
14991
|
PlayerEntity: 1,
|
|
14510
14992
|
CameraEntity: 2,
|
|
14511
|
-
|
|
14993
|
+
getEntityState: engine.entityContainer.getEntityState,
|
|
14512
14994
|
addTransport: crdtSystem.addTransport,
|
|
14513
14995
|
getCrdtState: crdtSystem.getCrdt,
|
|
14514
|
-
|
|
14996
|
+
entityContainer: engine.entityContainer
|
|
14515
14997
|
};
|
|
14516
14998
|
}
|
|
14517
14999
|
|
|
@@ -14597,7 +15079,7 @@
|
|
|
14597
15079
|
// @internal
|
|
14598
15080
|
engine.addSystem(function EventSystem() {
|
|
14599
15081
|
for (const [entity, event] of eventsMap) {
|
|
14600
|
-
if (
|
|
15082
|
+
if (engine.getEntityState(entity) === exports.EntityState.Removed) {
|
|
14601
15083
|
eventsMap.delete(entity);
|
|
14602
15084
|
continue;
|
|
14603
15085
|
}
|
|
@@ -41150,7 +41632,9 @@
|
|
|
41150
41632
|
}
|
|
41151
41633
|
},
|
|
41152
41634
|
filter(message) {
|
|
41153
|
-
if (
|
|
41635
|
+
if ((message.type === exports.CrdtMessageType.PUT_COMPONENT ||
|
|
41636
|
+
message.type === exports.CrdtMessageType.DELETE_COMPONENT) &&
|
|
41637
|
+
!componentIds.includes(message.componentId)) {
|
|
41154
41638
|
return false;
|
|
41155
41639
|
}
|
|
41156
41640
|
return !!message;
|
|
@@ -41178,6 +41662,7 @@
|
|
|
41178
41662
|
exports.BorderRect = BorderRect;
|
|
41179
41663
|
exports.Button = Button;
|
|
41180
41664
|
exports.CANVAS_ROOT_ENTITY = CANVAS_ROOT_ENTITY;
|
|
41665
|
+
exports.CRDT_MESSAGE_HEADER_LENGTH = CRDT_MESSAGE_HEADER_LENGTH;
|
|
41181
41666
|
exports.CameraMode = CameraMode;
|
|
41182
41667
|
exports.CameraModeArea = CameraModeArea;
|
|
41183
41668
|
exports.DEG2RAD = DEG2RAD;
|