@dcl/playground-assets 7.0.6-4153633895.commit-4aad233 → 7.0.6-4180146485.commit-9a7dde9

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/index.js CHANGED
@@ -11080,40 +11080,6 @@
11080
11080
 
11081
11081
  /* eslint-disable */
11082
11082
  function createBasePBPointerEventsResult() {
11083
- return { commands: [] };
11084
- }
11085
- /**
11086
- * @public
11087
- */
11088
- /**
11089
- * @internal
11090
- */
11091
- const PBPointerEventsResult = {
11092
- encode(message, writer = _m0.Writer.create()) {
11093
- for (const v of message.commands) {
11094
- PBPointerEventsResult_PointerCommand.encode(v, writer.uint32(10).fork()).ldelim();
11095
- }
11096
- return writer;
11097
- },
11098
- decode(input, length) {
11099
- const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
11100
- let end = length === undefined ? reader.len : reader.pos + length;
11101
- const message = createBasePBPointerEventsResult();
11102
- while (reader.pos < end) {
11103
- const tag = reader.uint32();
11104
- switch (tag >>> 3) {
11105
- case 1:
11106
- message.commands.push(PBPointerEventsResult_PointerCommand.decode(reader, reader.uint32()));
11107
- break;
11108
- default:
11109
- reader.skipType(tag & 7);
11110
- break;
11111
- }
11112
- }
11113
- return message;
11114
- },
11115
- };
11116
- function createBasePBPointerEventsResult_PointerCommand() {
11117
11083
  return { button: 0, hit: undefined, state: 0, timestamp: 0, analog: undefined };
11118
11084
  }
11119
11085
  /**
@@ -11122,7 +11088,7 @@
11122
11088
  /**
11123
11089
  * @internal
11124
11090
  */
11125
- const PBPointerEventsResult_PointerCommand = {
11091
+ const PBPointerEventsResult = {
11126
11092
  encode(message, writer = _m0.Writer.create()) {
11127
11093
  if (message.button !== 0) {
11128
11094
  writer.uint32(8).int32(message.button);
@@ -11144,7 +11110,7 @@
11144
11110
  decode(input, length) {
11145
11111
  const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
11146
11112
  let end = length === undefined ? reader.len : reader.pos + length;
11147
- const message = createBasePBPointerEventsResult_PointerCommand();
11113
+ const message = createBasePBPointerEventsResult();
11148
11114
  while (reader.pos < end) {
11149
11115
  const tag = reader.uint32();
11150
11116
  switch (tag >>> 3) {
@@ -12775,7 +12741,10 @@
12775
12741
  /** @public */ const MeshRenderer$2 = engine => engine.defineComponentFromSchema("core::MeshRenderer", MeshRendererSchema);
12776
12742
  /** @public */ const NftShape$1 = engine => engine.defineComponentFromSchema("core::NftShape", NftShapeSchema);
12777
12743
  /** @public */ const PointerEvents$1 = engine => engine.defineComponentFromSchema("core::PointerEvents", PointerEventsSchema);
12778
- /** @public */ const PointerEventsResult$1 = engine => engine.defineComponentFromSchema("core::PointerEventsResult", PointerEventsResultSchema);
12744
+ /** @public */ const PointerEventsResult$1 = (engine) => engine.defineValueSetComponentFromSchema("core::PointerEventsResult", PointerEventsResultSchema, {
12745
+ timestampFunction: (t) => t.timestamp,
12746
+ maxElements: 100
12747
+ });
12779
12748
  /** @public */ const PointerLock$1 = engine => engine.defineComponentFromSchema("core::PointerLock", PointerLockSchema);
12780
12749
  /** @public */ const Raycast$1 = engine => engine.defineComponentFromSchema("core::Raycast", RaycastSchema);
12781
12750
  /** @public */ const RaycastResult$1 = engine => engine.defineComponentFromSchema("core::RaycastResult", RaycastResultSchema);
@@ -13098,7 +13067,6 @@
13098
13067
  PBNftShape: PBNftShape,
13099
13068
  PBPointerEvents: PBPointerEvents,
13100
13069
  PBPointerEventsResult: PBPointerEventsResult,
13101
- PBPointerEventsResult_PointerCommand: PBPointerEventsResult_PointerCommand,
13102
13070
  PBPointerEvents_Entry: PBPointerEvents_Entry,
13103
13071
  PBPointerEvents_Info: PBPointerEvents_Info,
13104
13072
  PBPointerLock: PBPointerLock,
@@ -13239,8 +13207,13 @@
13239
13207
  return ((unsignedCRC32(bytes) + MAX_STATIC_COMPONENT) & 4294967295) >>> 0;
13240
13208
  }
13241
13209
 
13210
+ /* istanbul ignore file */
13211
+ const __DEV__ = (typeof DEBUG === 'boolean' && DEBUG) ||
13212
+ (typeof process === 'object' &&
13213
+ (process.env?.NODE_ENV !== 'production' || process.env?.NODE_ENV === 'development')) ||
13214
+ false;
13242
13215
  function checkNotThenable(t, error) {
13243
- if (globalThis.DEBUG) {
13216
+ if (__DEV__) {
13244
13217
  if (t && typeof t === 'object' && typeof t.then === 'function') {
13245
13218
  throw new Error(error);
13246
13219
  }
@@ -14144,7 +14117,8 @@
14144
14117
  CrdtMessageType[CrdtMessageType["PUT_COMPONENT"] = 1] = "PUT_COMPONENT";
14145
14118
  CrdtMessageType[CrdtMessageType["DELETE_COMPONENT"] = 2] = "DELETE_COMPONENT";
14146
14119
  CrdtMessageType[CrdtMessageType["DELETE_ENTITY"] = 3] = "DELETE_ENTITY";
14147
- CrdtMessageType[CrdtMessageType["MAX_MESSAGE_TYPE"] = 4] = "MAX_MESSAGE_TYPE";
14120
+ CrdtMessageType[CrdtMessageType["APPEND_VALUE"] = 4] = "APPEND_VALUE";
14121
+ CrdtMessageType[CrdtMessageType["MAX_MESSAGE_TYPE"] = 5] = "MAX_MESSAGE_TYPE";
14148
14122
  })(exports.CrdtMessageType || (exports.CrdtMessageType = {}));
14149
14123
  /**
14150
14124
  * @public
@@ -14317,6 +14291,54 @@
14317
14291
  DeleteComponent.read = read;
14318
14292
  })(exports.DeleteComponent || (exports.DeleteComponent = {}));
14319
14293
 
14294
+ /**
14295
+ * @internal
14296
+ */
14297
+ exports.AppendValueOperation = void 0;
14298
+ (function (AppendValueOperation) {
14299
+ AppendValueOperation.MESSAGE_HEADER_LENGTH = 16;
14300
+ /**
14301
+ * Call this function for an optimal writing data passing the ByteBuffer
14302
+ * already allocated
14303
+ */
14304
+ function write(entity, timestamp, componentId, data, buf) {
14305
+ // reserve the beginning
14306
+ const startMessageOffset = buf.incrementWriteOffset(CRDT_MESSAGE_HEADER_LENGTH + AppendValueOperation.MESSAGE_HEADER_LENGTH);
14307
+ // write body
14308
+ buf.writeBuffer(data, false);
14309
+ const messageLength = buf.currentWriteOffset() - startMessageOffset;
14310
+ // Write CrdtMessage header
14311
+ buf.setUint32(startMessageOffset, messageLength);
14312
+ buf.setUint32(startMessageOffset + 4, exports.CrdtMessageType.APPEND_VALUE);
14313
+ // Write ComponentOperation header
14314
+ buf.setUint32(startMessageOffset + 8, entity);
14315
+ buf.setUint32(startMessageOffset + 12, componentId);
14316
+ buf.setUint32(startMessageOffset + 16, timestamp);
14317
+ const newLocal = messageLength - AppendValueOperation.MESSAGE_HEADER_LENGTH - CRDT_MESSAGE_HEADER_LENGTH;
14318
+ buf.setUint32(startMessageOffset + 20, newLocal);
14319
+ }
14320
+ AppendValueOperation.write = write;
14321
+ function read(buf) {
14322
+ const header = exports.CrdtMessageProtocol.readHeader(buf);
14323
+ /* istanbul ignore if */
14324
+ if (!header) {
14325
+ return null;
14326
+ }
14327
+ /* istanbul ignore if */
14328
+ if (header.type !== exports.CrdtMessageType.APPEND_VALUE) {
14329
+ throw new Error('AppendValueOperation tried to read another message type.');
14330
+ }
14331
+ return {
14332
+ ...header,
14333
+ entityId: buf.readUint32(),
14334
+ componentId: buf.readUint32(),
14335
+ timestamp: buf.readUint32(),
14336
+ data: buf.readBuffer()
14337
+ };
14338
+ }
14339
+ AppendValueOperation.read = read;
14340
+ })(exports.AppendValueOperation || (exports.AppendValueOperation = {}));
14341
+
14320
14342
  /**
14321
14343
  * @internal
14322
14344
  */
@@ -14423,7 +14445,6 @@
14423
14445
  if (header.type === exports.CrdtMessageType.DELETE_COMPONENT) {
14424
14446
  const message = exports.DeleteComponent.read(buffer);
14425
14447
  receivedMessages.push({
14426
- ...header,
14427
14448
  ...message,
14428
14449
  transportId,
14429
14450
  messageBuffer: buffer.buffer().subarray(offset, buffer.currentReadOffset())
@@ -14432,7 +14453,6 @@
14432
14453
  else if (header.type === exports.CrdtMessageType.PUT_COMPONENT) {
14433
14454
  const message = exports.PutComponentOperation.read(buffer);
14434
14455
  receivedMessages.push({
14435
- ...header,
14436
14456
  ...message,
14437
14457
  transportId,
14438
14458
  messageBuffer: buffer.buffer().subarray(offset, buffer.currentReadOffset())
@@ -14441,7 +14461,14 @@
14441
14461
  else if (header.type === exports.CrdtMessageType.DELETE_ENTITY) {
14442
14462
  const message = exports.DeleteEntity.read(buffer);
14443
14463
  receivedMessages.push({
14444
- ...header,
14464
+ ...message,
14465
+ transportId,
14466
+ messageBuffer: buffer.buffer().subarray(offset, buffer.currentReadOffset())
14467
+ });
14468
+ }
14469
+ else if (header.type === exports.CrdtMessageType.APPEND_VALUE) {
14470
+ const message = exports.AppendValueOperation.read(buffer);
14471
+ receivedMessages.push({
14445
14472
  ...message,
14446
14473
  transportId,
14447
14474
  messageBuffer: buffer.buffer().subarray(offset, buffer.currentReadOffset())
@@ -14487,13 +14514,13 @@
14487
14514
  }
14488
14515
  const component = engine.getComponentOrNull(msg.componentId);
14489
14516
  if (component) {
14490
- const [conflictMessage] = component.updateFromCrdt(msg);
14517
+ const [conflictMessage, value] = component.updateFromCrdt(msg);
14491
14518
  if (conflictMessage) {
14492
14519
  const offset = bufferForOutdated.currentWriteOffset();
14493
14520
  if (conflictMessage.type === exports.CrdtMessageType.PUT_COMPONENT) {
14494
14521
  exports.PutComponentOperation.write(msg.entityId, conflictMessage.timestamp, conflictMessage.componentId, conflictMessage.data, bufferForOutdated);
14495
14522
  }
14496
- else {
14523
+ else if (conflictMessage.type === exports.CrdtMessageType.DELETE_COMPONENT) {
14497
14524
  exports.DeleteComponent.write(msg.entityId, component.componentId, conflictMessage.timestamp, bufferForOutdated);
14498
14525
  }
14499
14526
  outdatedMessages.push({
@@ -14504,7 +14531,7 @@
14504
14531
  else {
14505
14532
  // Add message to transport queue to be processed by others transports
14506
14533
  broadcastMessages.push(msg);
14507
- onProcessEntityComponentChange && onProcessEntityComponentChange(msg.entityId, msg.type, component);
14534
+ onProcessEntityComponentChange && onProcessEntityComponentChange(msg.entityId, msg.type, component, value);
14508
14535
  }
14509
14536
  }
14510
14537
  }
@@ -14543,11 +14570,19 @@
14543
14570
  else if (message.type === exports.CrdtMessageType.DELETE_COMPONENT) {
14544
14571
  exports.DeleteComponent.write(message.entityId, component.componentId, message.timestamp, buffer);
14545
14572
  }
14573
+ else if (message.type === exports.CrdtMessageType.APPEND_VALUE) {
14574
+ exports.AppendValueOperation.write(message.entityId, message.timestamp, message.componentId, message.data, buffer);
14575
+ }
14546
14576
  crdtMessages.push({
14547
14577
  ...message,
14548
14578
  messageBuffer: buffer.buffer().subarray(offset, buffer.currentWriteOffset())
14549
14579
  });
14550
- onProcessEntityComponentChange && onProcessEntityComponentChange(message.entityId, message.type, component);
14580
+ if (onProcessEntityComponentChange) {
14581
+ const rawValue = message.type === exports.CrdtMessageType.PUT_COMPONENT || message.type === exports.CrdtMessageType.APPEND_VALUE
14582
+ ? component.get(message.entityId)
14583
+ : undefined;
14584
+ onProcessEntityComponentChange(message.entityId, message.type, component, rawValue);
14585
+ }
14551
14586
  }
14552
14587
  }
14553
14588
  }
@@ -14658,7 +14693,7 @@
14658
14693
  timestamps.set(entity, newTimestamp);
14659
14694
  return newTimestamp;
14660
14695
  }
14661
- function createUpdateFromCrdt(componentId, timestamps, schema, data) {
14696
+ function createUpdateLwwFromCrdt(componentId, timestamps, schema, data) {
14662
14697
  /**
14663
14698
  * Process the received message only if the lamport number recieved is higher
14664
14699
  * than the stored one. If its lower, we spread it to the network to correct the peer.
@@ -14759,7 +14794,7 @@
14759
14794
  return [null, data.get(entity)];
14760
14795
  };
14761
14796
  }
14762
- function createGetCrdtMessages(componentId, timestamps, dirtyIterator, schema, data) {
14797
+ function createGetCrdtMessagesForLww(componentId, timestamps, dirtyIterator, schema, data) {
14763
14798
  return function* () {
14764
14799
  for (const entity of dirtyIterator) {
14765
14800
  const newTimestamp = incrementTimestamp(entity, timestamps);
@@ -14802,12 +14837,11 @@
14802
14837
  get componentName() {
14803
14838
  return componentName;
14804
14839
  },
14805
- default() {
14806
- return schema.create();
14807
- },
14808
- isDirty(entity) {
14809
- return dirtyIterator.has(entity);
14840
+ get componentType() {
14841
+ // a getter is used here to prevent accidental changes
14842
+ return 0 /* ComponentType.LastWriteWinElementSet */;
14810
14843
  },
14844
+ schema,
14811
14845
  has(entity) {
14812
14846
  return data.has(entity);
14813
14847
  },
@@ -14875,20 +14909,8 @@
14875
14909
  yield entity;
14876
14910
  }
14877
14911
  },
14878
- getCrdtUpdates: createGetCrdtMessages(componentId, timestamps, dirtyIterator, schema, data),
14879
- toBinary(entity) {
14880
- const component = data.get(entity);
14881
- if (!component) {
14882
- throw new Error(`[toBinary] Component ${componentName} for ${entity} not found`);
14883
- }
14884
- const writeBuffer = new ReadWriteByteBuffer();
14885
- schema.serialize(component, writeBuffer);
14886
- return writeBuffer;
14887
- },
14888
- updateFromCrdt: createUpdateFromCrdt(componentId, timestamps, schema, data),
14889
- deserialize(buffer) {
14890
- return schema.deserialize(buffer);
14891
- }
14912
+ getCrdtUpdates: createGetCrdtMessagesForLww(componentId, timestamps, dirtyIterator, schema, data),
14913
+ updateFromCrdt: createUpdateLwwFromCrdt(componentId, timestamps, schema, data)
14892
14914
  };
14893
14915
  }
14894
14916
 
@@ -14937,6 +14959,135 @@
14937
14959
  };
14938
14960
  }
14939
14961
 
14962
+ const emptyReadonlySet = freezeSet(new Set());
14963
+ function frozenError() {
14964
+ throw new Error('The set is frozen');
14965
+ }
14966
+ function freezeSet(set) {
14967
+ set.add = frozenError;
14968
+ set.clear = frozenError;
14969
+ return set;
14970
+ }
14971
+ function sortByTimestamp(a, b) {
14972
+ return a.timestamp > b.timestamp ? 1 : -1;
14973
+ }
14974
+ /**
14975
+ * @internal
14976
+ */
14977
+ function createValueSetComponentDefinitionFromSchema(componentName, componentId, schema, options) {
14978
+ const data = new Map();
14979
+ const dirtyIterator = new Set();
14980
+ const queuedCommands = [];
14981
+ // only sort the array if the latest (N) element has a timestamp <= N-1
14982
+ function shouldSort(row) {
14983
+ const len = row.raw.length;
14984
+ if (len > 1 && row.raw[len - 1].timestamp <= row.raw[len - 2].timestamp) {
14985
+ return true;
14986
+ }
14987
+ return false;
14988
+ }
14989
+ function gotUpdated(entity) {
14990
+ const row = data.get(entity);
14991
+ /* istanbul ignore else */
14992
+ if (row) {
14993
+ if (shouldSort(row)) {
14994
+ row.raw.sort(sortByTimestamp);
14995
+ }
14996
+ while (row.raw.length > options.maxElements) {
14997
+ row.raw.shift();
14998
+ }
14999
+ const frozenSet = freezeSet(new Set(row?.raw.map(($) => $.value)));
15000
+ row.frozenSet = frozenSet;
15001
+ return frozenSet;
15002
+ }
15003
+ else {
15004
+ /* istanbul ignore next */
15005
+ return emptyReadonlySet;
15006
+ }
15007
+ }
15008
+ function append(entity, value) {
15009
+ let row = data.get(entity);
15010
+ if (!row) {
15011
+ row = { raw: [], frozenSet: emptyReadonlySet };
15012
+ data.set(entity, row);
15013
+ }
15014
+ const usedValue = schema.extend ? schema.extend(value) : value;
15015
+ const timestamp = options.timestampFunction(usedValue);
15016
+ if (__DEV__) {
15017
+ // only freeze the objects in dev mode to warn the developers because
15018
+ // it is an expensive operation
15019
+ Object.freeze(usedValue);
15020
+ }
15021
+ row.raw.push({ value: usedValue, timestamp });
15022
+ return { set: gotUpdated(entity), value: usedValue };
15023
+ }
15024
+ const ret = {
15025
+ get componentId() {
15026
+ return componentId;
15027
+ },
15028
+ get componentName() {
15029
+ return componentName;
15030
+ },
15031
+ get componentType() {
15032
+ // a getter is used here to prevent accidental changes
15033
+ return 1 /* ComponentType.GrowOnlyValueSet */;
15034
+ },
15035
+ schema,
15036
+ has(entity) {
15037
+ return data.has(entity);
15038
+ },
15039
+ entityDeleted(entity) {
15040
+ data.delete(entity);
15041
+ },
15042
+ get(entity) {
15043
+ const values = data.get(entity);
15044
+ if (values) {
15045
+ return values.frozenSet;
15046
+ }
15047
+ else {
15048
+ return emptyReadonlySet;
15049
+ }
15050
+ },
15051
+ addValue(entity, rawValue) {
15052
+ const { set, value } = append(entity, rawValue);
15053
+ dirtyIterator.add(entity);
15054
+ const buf = new ReadWriteByteBuffer();
15055
+ schema.serialize(value, buf);
15056
+ queuedCommands.push({
15057
+ componentId,
15058
+ data: buf.toBinary(),
15059
+ entityId: entity,
15060
+ timestamp: 0,
15061
+ type: exports.CrdtMessageType.APPEND_VALUE
15062
+ });
15063
+ return set;
15064
+ },
15065
+ *iterator() {
15066
+ for (const [entity, component] of data) {
15067
+ yield [entity, component.frozenSet];
15068
+ }
15069
+ },
15070
+ *dirtyIterator() {
15071
+ for (const entity of dirtyIterator) {
15072
+ yield entity;
15073
+ }
15074
+ },
15075
+ getCrdtUpdates() {
15076
+ // return a copy of the commands, and then clear the local copy
15077
+ dirtyIterator.clear();
15078
+ return queuedCommands.splice(0, queuedCommands.length);
15079
+ },
15080
+ updateFromCrdt(_body) {
15081
+ if (_body.type === exports.CrdtMessageType.APPEND_VALUE) {
15082
+ const buf = new ReadWriteByteBuffer(_body.data);
15083
+ append(_body.entityId, schema.deserialize(buf));
15084
+ }
15085
+ return [null, undefined];
15086
+ }
15087
+ };
15088
+ return ret;
15089
+ }
15090
+
14940
15091
  const InputCommands = [
14941
15092
  0 /* InputAction.IA_POINTER */,
14942
15093
  1 /* InputAction.IA_PRIMARY */,
@@ -14952,69 +15103,71 @@
14952
15103
  12 /* InputAction.IA_ACTION_5 */,
14953
15104
  13 /* InputAction.IA_ACTION_6 */
14954
15105
  ];
14955
- const InternalInputStateSchema = {
14956
- timestampLastUpdate: exports.Schemas.Number,
14957
- currentTimestamp: exports.Schemas.Number,
14958
- buttonState: exports.Schemas.Array(exports.Schemas.Map({
14959
- value: exports.Schemas.Boolean,
14960
- ts: exports.Schemas.Number
14961
- }))
14962
- };
14963
- const TimestampUpdateSystemPriority = 1 << 20;
14964
- const ButtonStateUpdateSystemPriority = 0;
15106
+ const InputStateUpdateSystemPriority = 1 << 20;
14965
15107
  /**
14966
15108
  * @internal
14967
15109
  */
14968
15110
  function createInputSystem(engine) {
14969
15111
  const PointerEventsResult = PointerEventsResult$1(engine);
14970
- const InternalInputStateComponent = engine.defineComponent('@dcl/sdk/InternalInputStateSchema', InternalInputStateSchema);
14971
- InternalInputStateComponent.create(engine.RootEntity, {
14972
- buttonState: Array.from({ length: InputCommands.length }, () => ({
14973
- ts: 0,
14974
- value: false
14975
- }))
14976
- });
14977
- function timestampUpdateSystem() {
14978
- const state = InternalInputStateComponent.get(engine.RootEntity);
14979
- if (state.currentTimestamp > state.timestampLastUpdate) {
14980
- InternalInputStateComponent.getMutable(engine.RootEntity).timestampLastUpdate = state.currentTimestamp;
14981
- }
14982
- }
14983
- function* commandIterator() {
14984
- for (const [, value] of engine.getEntitiesWith(PointerEventsResult)) {
14985
- yield* value.commands;
15112
+ const globalState = {
15113
+ previousFrameMaxTimestamp: 0,
15114
+ currentFrameMaxTimestamp: 0,
15115
+ buttonState: new Map()
15116
+ };
15117
+ function findLastAction(pointerEventType, inputAction, entity) {
15118
+ const ascendingTimestampIterator = PointerEventsResult.get(entity);
15119
+ for (const command of Array.from(ascendingTimestampIterator).reverse()) {
15120
+ if (command.button === inputAction && command.state === pointerEventType) {
15121
+ return command;
15122
+ }
14986
15123
  }
14987
15124
  }
14988
- function findLastAction(pointerEventType, inputAction, entity) {
14989
- let commandToReturn = undefined;
14990
- for (const command of commandIterator()) {
14991
- if (command.button === inputAction &&
14992
- command.state === pointerEventType &&
14993
- (!entity || (command.hit && entity === command.hit.entityId))) {
14994
- if (!commandToReturn || command.timestamp >= commandToReturn.timestamp)
14995
- commandToReturn = command;
15125
+ function* findCommandsByActionDescending(inputAction, entity) {
15126
+ const ascendingTimestampIterator = PointerEventsResult.get(entity);
15127
+ for (const command of Array.from(ascendingTimestampIterator).reverse()) {
15128
+ if (command.button === inputAction) {
15129
+ yield command;
14996
15130
  }
14997
15131
  }
14998
- return commandToReturn;
14999
15132
  }
15000
15133
  function buttonStateUpdateSystem() {
15001
- const component = PointerEventsResult.getOrNull(engine.RootEntity);
15002
- if (!component)
15003
- return;
15004
- const state = InternalInputStateComponent.getMutable(engine.RootEntity);
15005
- for (const command of commandIterator()) {
15006
- if (command.timestamp > state.buttonState[command.button].ts) {
15007
- if (command.state === 1 /* PointerEventType.PET_DOWN */) {
15008
- state.buttonState[command.button].value = true;
15134
+ // first store the previous' frame timestamp
15135
+ let maxTimestamp = globalState.currentFrameMaxTimestamp;
15136
+ globalState.previousFrameMaxTimestamp = maxTimestamp;
15137
+ // then iterate over all new commands
15138
+ for (const [, commands] of engine.getEntitiesWith(PointerEventsResult)) {
15139
+ // TODO: adapt the gset component to have a cached "reversed" option by default
15140
+ const arrayCommands = Array.from(commands);
15141
+ for (let i = arrayCommands.length - 1; i >= 0; i--) {
15142
+ const command = arrayCommands[i];
15143
+ if (command.timestamp > maxTimestamp) {
15144
+ maxTimestamp = command.timestamp;
15009
15145
  }
15010
- else if (command.state === 0 /* PointerEventType.PET_UP */) {
15011
- state.buttonState[command.button].value = false;
15146
+ if (command.state === 0 /* PointerEventType.PET_UP */ || command.state === 1 /* PointerEventType.PET_DOWN */) {
15147
+ const prevCommand = globalState.buttonState.get(command.button);
15148
+ if (!prevCommand || command.timestamp > prevCommand.timestamp) {
15149
+ globalState.buttonState.set(command.button, command);
15150
+ }
15151
+ else {
15152
+ // since we are iterating a descending array, we can early finish the
15153
+ // loop
15154
+ break;
15155
+ }
15012
15156
  }
15013
15157
  }
15014
15158
  }
15159
+ // update current frame's max timestamp
15160
+ globalState.currentFrameMaxTimestamp = maxTimestamp;
15161
+ }
15162
+ engine.addSystem(buttonStateUpdateSystem, InputStateUpdateSystemPriority, '@dcl/ecs#inputSystem');
15163
+ function timestampIsCurrentFrame(timestamp) {
15164
+ if (timestamp > globalState.previousFrameMaxTimestamp && timestamp <= globalState.currentFrameMaxTimestamp) {
15165
+ return true;
15166
+ }
15167
+ else {
15168
+ return false;
15169
+ }
15015
15170
  }
15016
- engine.addSystem(buttonStateUpdateSystem, ButtonStateUpdateSystemPriority, '@dcl/ecs#buttonStateUpdateSystem');
15017
- engine.addSystem(timestampUpdateSystem, TimestampUpdateSystemPriority, '@dcl/ecs#timestampUpdateSystem');
15018
15171
  function getClick(inputAction, entity) {
15019
15172
  if (inputAction !== 3 /* InputAction.IA_ANY */) {
15020
15173
  return findClick(inputAction, entity);
@@ -15027,18 +15180,27 @@
15027
15180
  return null;
15028
15181
  }
15029
15182
  function findClick(inputAction, entity) {
15030
- // We search the last DOWN command sorted by timestamp
15031
- const down = findLastAction(1 /* PointerEventType.PET_DOWN */, inputAction, entity);
15032
- // We search the last UP command sorted by timestamp
15033
- if (!down)
15034
- return null;
15035
- const up = findLastAction(0 /* PointerEventType.PET_UP */, inputAction, entity);
15036
- if (!up)
15183
+ let down = null;
15184
+ let up = null;
15185
+ // We search the last UP & DOWN command sorted by timestamp descending
15186
+ for (const it of findCommandsByActionDescending(inputAction, entity)) {
15187
+ if (!up) {
15188
+ if (it.state === 0 /* PointerEventType.PET_UP */) {
15189
+ up = it;
15190
+ continue;
15191
+ }
15192
+ }
15193
+ else if (!down) {
15194
+ if (it.state === 1 /* PointerEventType.PET_DOWN */) {
15195
+ down = it;
15196
+ break;
15197
+ }
15198
+ }
15199
+ }
15200
+ if (!up || !down)
15037
15201
  return null;
15038
- const state = InternalInputStateComponent.get(engine.RootEntity);
15039
15202
  // If the DOWN command has happen before the UP commands, it means that that a clicked has happen
15040
- if (down.timestamp < up.timestamp && up.timestamp > state.timestampLastUpdate) {
15041
- InternalInputStateComponent.getMutable(engine.RootEntity).currentTimestamp = Math.max(up.timestamp, state.currentTimestamp);
15203
+ if (down.timestamp < up.timestamp && timestampIsCurrentFrame(up.timestamp)) {
15042
15204
  return { up, down };
15043
15205
  }
15044
15206
  return null;
@@ -15059,38 +15221,45 @@
15059
15221
  const command = findLastAction(pointerEventType, inputAction, entity);
15060
15222
  if (!command)
15061
15223
  return null;
15062
- const state = InternalInputStateComponent.get(engine.RootEntity);
15063
- if (command.timestamp > state.timestampLastUpdate) {
15064
- InternalInputStateComponent.getMutable(engine.RootEntity).currentTimestamp = Math.max(command.timestamp, state.currentTimestamp);
15224
+ if (timestampIsCurrentFrame(command.timestamp)) {
15065
15225
  return command;
15066
15226
  }
15067
15227
  else {
15068
15228
  return null;
15069
15229
  }
15070
15230
  }
15231
+ // returns true if there was a DOWN (in any past frame), and then an UP in the last frame
15071
15232
  function isClicked(inputAction, entity) {
15072
15233
  return getClick(inputAction, entity) !== null;
15073
15234
  }
15235
+ // returns true if the provided last action was triggered in the last frame
15074
15236
  function isTriggered(inputAction, pointerEventType, entity) {
15075
- return getInputCommand(inputAction, pointerEventType, entity) !== null;
15237
+ const command = findLastAction(pointerEventType, inputAction, entity);
15238
+ return (command && timestampIsCurrentFrame(command.timestamp)) || false;
15076
15239
  }
15240
+ // returns the global state of the input. This global state is updated from the system
15077
15241
  function isPressed(inputAction) {
15078
- return InternalInputStateComponent.get(engine.RootEntity).buttonState[inputAction].value;
15242
+ return globalState.buttonState.get(inputAction)?.state === 1 /* PointerEventType.PET_DOWN */;
15079
15243
  }
15080
15244
  return {
15081
- // @public
15082
15245
  isPressed,
15083
- // @internal
15084
15246
  getClick,
15085
- // @public
15086
15247
  getInputCommand,
15087
- // @internal
15088
15248
  isClicked,
15089
- // @public
15090
15249
  isTriggered
15091
15250
  };
15092
15251
  }
15093
15252
 
15253
+ /**
15254
+ * Component types are used to pick the wire protocol and the conflict resolution algorithm
15255
+ * @public
15256
+ */
15257
+ exports.ComponentType = void 0;
15258
+ (function (ComponentType) {
15259
+ ComponentType[ComponentType["LastWriteWinElementSet"] = 0] = "LastWriteWinElementSet";
15260
+ ComponentType[ComponentType["GrowOnlyValueSet"] = 1] = "GrowOnlyValueSet";
15261
+ })(exports.ComponentType || (exports.ComponentType = {}));
15262
+
15094
15263
  function preEngine() {
15095
15264
  const entityContainer = EntityContainer();
15096
15265
  const componentsDefinition = new Map();
@@ -15146,6 +15315,20 @@
15146
15315
  componentsDefinition.set(componentId, newComponent);
15147
15316
  return newComponent;
15148
15317
  }
15318
+ function defineValueSetComponentFromSchema(componentName, schema, options) {
15319
+ /* istanbul ignore next */
15320
+ if (sealed)
15321
+ throw new Error('Engine is already sealed. No components can be added at this stage');
15322
+ const componentId = componentNumberFromName(componentName);
15323
+ const prev = componentsDefinition.get(componentId);
15324
+ if (prev) {
15325
+ // TODO: assert spec === prev.spec
15326
+ return prev;
15327
+ }
15328
+ const newComponent = createValueSetComponentDefinitionFromSchema(componentName, componentId, schema, options);
15329
+ componentsDefinition.set(componentId, newComponent);
15330
+ return newComponent;
15331
+ }
15149
15332
  function defineComponent(componentName, mapSpec, constructorDefault) {
15150
15333
  if (sealed)
15151
15334
  throw new Error('Engine is already sealed. No components can be added at this stage');
@@ -15241,6 +15424,7 @@
15241
15424
  removeSystem,
15242
15425
  defineComponent,
15243
15426
  defineComponentFromSchema,
15427
+ defineValueSetComponentFromSchema,
15244
15428
  getEntitiesWith,
15245
15429
  getComponent,
15246
15430
  getComponentOrNull,
@@ -15276,6 +15460,7 @@
15276
15460
  removeSystem: partialEngine.removeSystem,
15277
15461
  defineComponent: partialEngine.defineComponent,
15278
15462
  defineComponentFromSchema: partialEngine.defineComponentFromSchema,
15463
+ defineValueSetComponentFromSchema: partialEngine.defineValueSetComponentFromSchema,
15279
15464
  registerComponentDefinition: partialEngine.registerComponentDefinition,
15280
15465
  getEntitiesWith: partialEngine.getEntitiesWith,
15281
15466
  getComponent: partialEngine.getComponent,
@@ -40862,6 +41047,39 @@
40862
41047
  var reactReconcilerExports = requireReactReconciler();
40863
41048
  var Reconciler = /*@__PURE__*/getDefaultExportFromCjs(reactReconcilerExports);
40864
41049
 
41050
+ const parseFont = {
41051
+ 'sans-serif': 0 /* Font.F_SANS_SERIF */,
41052
+ serif: 1 /* Font.F_SERIF */,
41053
+ monospace: 2 /* Font.F_MONOSPACE */
41054
+ };
41055
+ /**
41056
+ * @internal
41057
+ */
41058
+ function getFont(font) {
41059
+ if (!font)
41060
+ return undefined;
41061
+ return { font: parseFont[font] };
41062
+ }
41063
+ const parseTextAlign = {
41064
+ 'top-left': 0 /* TextAlignMode.TAM_TOP_LEFT */,
41065
+ 'top-center': 1 /* TextAlignMode.TAM_TOP_CENTER */,
41066
+ 'top-right': 2 /* TextAlignMode.TAM_TOP_RIGHT */,
41067
+ 'middle-left': 3 /* TextAlignMode.TAM_MIDDLE_LEFT */,
41068
+ 'middle-center': 4 /* TextAlignMode.TAM_MIDDLE_CENTER */,
41069
+ 'middle-right': 5 /* TextAlignMode.TAM_MIDDLE_RIGHT */,
41070
+ 'bottom-left': 6 /* TextAlignMode.TAM_BOTTOM_LEFT */,
41071
+ 'bottom-center': 7 /* TextAlignMode.TAM_BOTTOM_CENTER */,
41072
+ 'bottom-right': 8 /* TextAlignMode.TAM_BOTTOM_RIGHT */
41073
+ };
41074
+ /**
41075
+ * @internal
41076
+ */
41077
+ function getTextAlign(textAlign) {
41078
+ if (!textAlign)
41079
+ return undefined;
41080
+ return { textAlign: parseTextAlign[textAlign] };
41081
+ }
41082
+
40865
41083
  const parseTextureMode = {
40866
41084
  'nine-slices': 0 /* BackgroundTextureMode.NINE_SLICES */,
40867
41085
  center: 1 /* BackgroundTextureMode.CENTER */,
@@ -40947,7 +41165,7 @@
40947
41165
  if (val === undefined || val === null) {
40948
41166
  return [undefined, 0 /* YGUnit.YGU_UNDEFINED */];
40949
41167
  }
40950
- if (typeof val === 'number') {
41168
+ if (typeof val === 'number' || (typeof val === 'string' && !isNaN(Number(val)))) {
40951
41169
  return [Number(val), 1 /* YGUnit.YGU_POINT */];
40952
41170
  }
40953
41171
  if (isPercent(val)) {
@@ -40958,20 +41176,39 @@
40958
41176
  }
40959
41177
  return [undefined, 0 /* YGUnit.YGU_UNDEFINED */];
40960
41178
  }
40961
- // position: { top: '1px' } => { positionTop: 1, positionTopUnit: YGUnit.YGU_Point }
40962
41179
  function parsePosition(position = {}, prop) {
40963
- const obj = {};
40964
- for (const key in position) {
40965
- const typedKey = key;
40966
- const propKey = `${prop}${capitalize(typedKey)}`;
40967
- const propKeyUnit = `${prop}${capitalize(typedKey)}Unit`;
40968
- const [value, unit] = parsePositionUnit(position[typedKey]);
40969
- if (value === undefined)
40970
- continue;
40971
- obj[propKeyUnit] = unit;
40972
- obj[propKey] = value;
40973
- }
40974
- return obj;
41180
+ if (typeof position === 'object') {
41181
+ const obj = {};
41182
+ for (const key in position) {
41183
+ const typedKey = key;
41184
+ const propKey = `${prop}${capitalize(typedKey)}`;
41185
+ const propKeyUnit = `${prop}${capitalize(typedKey)}Unit`;
41186
+ const [value, unit] = parsePositionUnit(position[typedKey]);
41187
+ if (value === undefined)
41188
+ continue;
41189
+ obj[propKeyUnit] = unit;
41190
+ obj[propKey] = value;
41191
+ }
41192
+ return obj;
41193
+ }
41194
+ if (typeof position === 'number') {
41195
+ return parsePosition({ top: position, left: position, right: position, bottom: position }, prop);
41196
+ }
41197
+ const values = position.split(' ').filter((a) => a !== '');
41198
+ if (values.length === 1) {
41199
+ const [value] = values;
41200
+ return parsePosition({ top: value, left: value, right: value, bottom: value }, prop);
41201
+ }
41202
+ if (values.length === 2) {
41203
+ const [topBottom, rigthLeft] = values;
41204
+ return parsePosition({ top: topBottom, left: rigthLeft, right: rigthLeft, bottom: topBottom }, prop);
41205
+ }
41206
+ if (values.length === 3) {
41207
+ const [top, rigthLeft, bottom] = values;
41208
+ return parsePosition({ top, left: rigthLeft, right: rigthLeft, bottom }, prop);
41209
+ }
41210
+ const [top, right, bottom, left] = values;
41211
+ return parsePosition({ top, right, bottom, left }, prop);
40975
41212
  }
40976
41213
  function parseSize(val, key) {
40977
41214
  const unitKey = `${key}Unit`;
@@ -41012,8 +41249,8 @@
41012
41249
  /**
41013
41250
  * @internal
41014
41251
  */
41015
- function getAlign(prop, align, defaultValue) {
41016
- const value = align ? parseAligns[align] : defaultValue;
41252
+ function getAlign(prop, align) {
41253
+ const value = parseAligns[align];
41017
41254
  return { [prop]: value };
41018
41255
  }
41019
41256
  const parseAligns = {
@@ -41043,7 +41280,7 @@
41043
41280
  * @internal
41044
41281
  */
41045
41282
  function getFlexWrap(flexWrap) {
41046
- const value = flexWrap ? parseFlexWrap[flexWrap] : 1 /* YGWrap.YGW_WRAP */;
41283
+ const value = parseFlexWrap[flexWrap];
41047
41284
  return { flexWrap: value };
41048
41285
  }
41049
41286
  const parseFlexWrap = {
@@ -41080,6 +41317,12 @@
41080
41317
  */
41081
41318
  const CANVAS_ROOT_ENTITY = 0;
41082
41319
  const defaultUiTransform = {
41320
+ overflow: 0 /* YGOverflow.YGO_VISIBLE */,
41321
+ display: 0 /* YGDisplay.YGD_FLEX */,
41322
+ justifyContent: 0 /* YGJustify.YGJ_FLEX_START */,
41323
+ alignSelf: 0 /* YGAlign.YGA_AUTO */,
41324
+ flexDirection: 0 /* YGFlexDirection.YGFD_ROW */,
41325
+ positionType: 0 /* YGPositionType.YGPT_RELATIVE */,
41083
41326
  parent: CANVAS_ROOT_ENTITY,
41084
41327
  rightOf: 0,
41085
41328
  flexBasis: 0,
@@ -41127,7 +41370,7 @@
41127
41370
  */
41128
41371
 
41129
41372
  function parseUiTransform(props = {}) {
41130
- const { height, minHeight, maxHeight, width, minWidth, maxWidth, ...otherProps } = props;
41373
+ const { height, minHeight, maxHeight, width, minWidth, maxWidth, alignItems, alignContent, flexWrap, ...otherProps } = props;
41131
41374
  return {
41132
41375
  ...defaultUiTransform,
41133
41376
  ...otherProps,
@@ -41141,14 +41384,15 @@
41141
41384
  ...parseSize(props.minWidth, 'minWidth'),
41142
41385
  ...parseSize(props.maxWidth, 'maxWidth'),
41143
41386
  ...getDisplay(props.display),
41144
- ...getAlign('alignContent', props.alignContent, 1 /* YGAlign.YGA_FLEX_START */),
41145
- ...getAlign('alignSelf', props.alignSelf, 1 /* YGAlign.YGA_FLEX_START */),
41146
- ...getAlign('alignItems', props.alignItems, 1 /* YGAlign.YGA_FLEX_START */),
41387
+ ...getAlign('alignSelf', props.alignSelf ?? 'auto'),
41147
41388
  ...getJustify(props.justifyContent),
41148
41389
  ...getFlexDirection(props.flexDirection),
41149
- ...getFlexWrap(props.flexWrap),
41150
41390
  ...getOverflow(props.overflow),
41151
- ...getPoistionType(props.positionType)
41391
+ ...getPoistionType(props.positionType),
41392
+ // Optional values
41393
+ ...(alignContent && getAlign('alignContent', alignContent)),
41394
+ ...(alignItems && getAlign('alignItems', alignItems)),
41395
+ ...(flexWrap && getFlexWrap(flexWrap))
41152
41396
  };
41153
41397
  }
41154
41398
 
@@ -41176,39 +41420,6 @@
41176
41420
  */
41177
41421
  const isListener = (key) => listenersKey.includes(key);
41178
41422
 
41179
- const parseFont = {
41180
- 'sans-serif': 0 /* Font.F_SANS_SERIF */,
41181
- serif: 1 /* Font.F_SERIF */,
41182
- monospace: 2 /* Font.F_MONOSPACE */
41183
- };
41184
- /**
41185
- * @internal
41186
- */
41187
- function getFont(font) {
41188
- if (!font)
41189
- return undefined;
41190
- return { font: parseFont[font] };
41191
- }
41192
- const parseTextAlign = {
41193
- 'top-left': 0 /* TextAlignMode.TAM_TOP_LEFT */,
41194
- 'top-center': 1 /* TextAlignMode.TAM_TOP_CENTER */,
41195
- 'top-right': 2 /* TextAlignMode.TAM_TOP_RIGHT */,
41196
- 'middle-left': 3 /* TextAlignMode.TAM_MIDDLE_LEFT */,
41197
- 'middle-center': 4 /* TextAlignMode.TAM_MIDDLE_CENTER */,
41198
- 'middle-right': 5 /* TextAlignMode.TAM_MIDDLE_RIGHT */,
41199
- 'bottom-left': 6 /* TextAlignMode.TAM_BOTTOM_LEFT */,
41200
- 'bottom-center': 7 /* TextAlignMode.TAM_BOTTOM_CENTER */,
41201
- 'bottom-right': 8 /* TextAlignMode.TAM_BOTTOM_RIGHT */
41202
- };
41203
- /**
41204
- * @internal
41205
- */
41206
- function getTextAlign(textAlign) {
41207
- if (!textAlign)
41208
- return undefined;
41209
- return { textAlign: parseTextAlign[textAlign] };
41210
- }
41211
-
41212
41423
  function parseUiDropdown(props) {
41213
41424
  const { textAlign, font, ...otherProps } = props;
41214
41425
  return {
@@ -41377,7 +41588,14 @@
41377
41588
  */
41378
41589
 
41379
41590
  function UiEntity(props) {
41380
- return ReactEcs$1.createElement("entity", { ...parseProps(props) });
41591
+ const uiText = props.uiText && {
41592
+ uiText: {
41593
+ ...props.uiText,
41594
+ ...getFont(props.uiText.font),
41595
+ ...getTextAlign(props.uiText.textAlign)
41596
+ }
41597
+ };
41598
+ return ReactEcs$1.createElement("entity", { ...parseProps(props), ...uiText });
41381
41599
  }
41382
41600
 
41383
41601
  function propsChanged(component, prevProps, nextProps) {
@@ -42147,8 +42365,7 @@
42147
42365
  }
42148
42366
  },
42149
42367
  filter(message) {
42150
- if ((message.type === exports.CrdtMessageType.PUT_COMPONENT || message.type === exports.CrdtMessageType.DELETE_COMPONENT) &&
42151
- message.componentId > MAX_STATIC_COMPONENT) {
42368
+ if (message.componentId > MAX_STATIC_COMPONENT) {
42152
42369
  return false;
42153
42370
  }
42154
42371
  return !!message;
@@ -42235,7 +42452,6 @@
42235
42452
  exports.PBNftShape = PBNftShape;
42236
42453
  exports.PBPointerEvents = PBPointerEvents;
42237
42454
  exports.PBPointerEventsResult = PBPointerEventsResult;
42238
- exports.PBPointerEventsResult_PointerCommand = PBPointerEventsResult_PointerCommand;
42239
42455
  exports.PBPointerEvents_Entry = PBPointerEvents_Entry;
42240
42456
  exports.PBPointerEvents_Info = PBPointerEvents_Info;
42241
42457
  exports.PBPointerLock = PBPointerLock;
@@ -42279,19 +42495,15 @@
42279
42495
  exports.VideoTexture = VideoTexture;
42280
42496
  exports.VisibilityComponent = VisibilityComponent;
42281
42497
  exports.components = index;
42282
- exports.createComponentDefinitionFromSchema = createComponentDefinitionFromSchema;
42283
42498
  exports.createEthereumProvider = createEthereumProvider;
42284
- exports.createGetCrdtMessages = createGetCrdtMessages;
42285
42499
  exports.createInputSystem = createInputSystem;
42286
42500
  exports.createPointerEventSystem = createPointerEventSystem;
42287
42501
  exports.createReactBasedUiSystem = createReactBasedUiSystem;
42288
42502
  exports.createTaskSystem = createTaskSystem;
42289
- exports.createUpdateFromCrdt = createUpdateFromCrdt;
42290
42503
  exports.cyclicParentingChecker = cyclicParentingChecker;
42291
42504
  exports.deepReadonly = deepReadonly;
42292
42505
  exports.engine = engine;
42293
42506
  exports.executeTask = executeTask;
42294
- exports.incrementTimestamp = incrementTimestamp;
42295
42507
  exports.inputSystem = inputSystem;
42296
42508
  exports.isListener = isListener;
42297
42509
  exports.onCommsMessage = onCommsMessage;