dredless 1.0.1 → 1.1.1

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.
@@ -4068,7 +4068,6 @@
4068
4068
  firstRecord: () => firstRecord,
4069
4069
  isAquaShielderBotState: () => isAquaShielderBotState,
4070
4070
  isBlueRusherBotState: () => isBlueRusherBotState,
4071
- isBoulderBotExclusion: () => isBoulderBotExclusion,
4072
4071
  isCowardBossState: () => isCowardBossState,
4073
4072
  isLazerEnthusiastBotState: () => isLazerEnthusiastBotState,
4074
4073
  isNavigationDestination: () => isNavigationDestination,
@@ -4095,11 +4094,13 @@
4095
4094
  pushCapped: () => pushCapped,
4096
4095
  qKey: () => qKey,
4097
4096
  scaledSizeSummary: () => scaledSizeSummary,
4097
+ summarizeBall: () => summarizeBall,
4098
4098
  summarizeBlueprintPreview: () => summarizeBlueprintPreview,
4099
4099
  summarizeBot: () => summarizeBot,
4100
4100
  summarizeCannon: () => summarizeCannon,
4101
4101
  summarizeCargoEjector: () => summarizeCargoEjector,
4102
4102
  summarizeCargoHatch: () => summarizeCargoHatch,
4103
+ summarizeCombatBeams: () => summarizeCombatBeams,
4103
4104
  summarizeCommsStation: () => summarizeCommsStation,
4104
4105
  summarizeDockingSpring: () => summarizeDockingSpring,
4105
4106
  summarizeDoor: () => summarizeDoor,
@@ -4117,8 +4118,11 @@
4117
4118
  summarizeNavigationUnit: () => summarizeNavigationUnit,
4118
4119
  summarizePlayer: () => summarizePlayer,
4119
4120
  summarizePlayerPreview: () => summarizePlayerPreview,
4121
+ summarizeProjectile: () => summarizeProjectile,
4120
4122
  summarizePusher: () => summarizePusher,
4121
4123
  summarizePusherBeam: () => summarizePusherBeam,
4124
+ summarizeRcd: () => summarizeRcd,
4125
+ summarizeRecycler: () => summarizeRecycler,
4122
4126
  summarizeShieldGenerator: () => summarizeShieldGenerator,
4123
4127
  summarizeShieldProjector: () => summarizeShieldProjector,
4124
4128
  summarizeShipControl: () => summarizeShipControl,
@@ -4552,19 +4556,13 @@
4552
4556
  };
4553
4557
  var LABEL_STATE_SPEC = {
4554
4558
  name: "label_state",
4555
- read(reader, record, mask) {
4556
- if (mask & 1) record.blob20 = reader.readBlob();
4557
- if (mask & 2) {
4558
- if (mask & 1) record.blob24 = reader.readBlob();
4559
- else record.q20 = (record.q20 || 0) + reader.readFieldDelta();
4560
- }
4561
- if (mask & 4) record.q28 = (record.q28 || 0) + reader.readFieldDelta();
4562
- if (mask & 8) {
4563
- if (mask & 1) record.q32 = (record.q32 || 0) + reader.readFieldDelta();
4564
- else record.blob28 = reader.readBlob();
4565
- }
4566
- if (mask & 16) record.q36 = (record.q36 || 0) + reader.readFieldDelta();
4567
- }
4559
+ // Packed flag first, two independent text blobs,
4560
+ // then two numeric deltas. Field types never depend on another mask bit.
4561
+ // Keep the existing summary keys for the strings and colors.
4562
+ packedBeforeValues: true,
4563
+ packedBits: [{ bit: 16, offset: 36 }],
4564
+ blobs: [{ bit: 1, offset: 20 }, { bit: 2, offset: 24 }],
4565
+ fields: numericFields({ 4: 28, 8: 32 })
4568
4566
  };
4569
4567
  var SIMPLE_LABEL_STATE_SPEC = {
4570
4568
  name: "label_state",
@@ -4662,6 +4660,10 @@
4662
4660
  [11, { name: "numeric_sparse", fields: numericFields({ 1: 20, 2: 24, 4: 28, 8: 32, 16: 36 }) }],
4663
4661
  [12, { name: "numeric_sparse", fields: numericFields({ 1: 20, 2: 24, 4: 28, 8: 32 }) }],
4664
4662
  [14, { name: "size_state", fields: numericFields({ 1: 20, 2: 24, 4: 28, 8: 32, 16: 36, 32: 40, 64: 44 }) }],
4663
+ [15, {
4664
+ name: "combat_beams",
4665
+ fields: numericFields({ 1: 20, 2: 24, 4: 28, 8: 32, 16: 36, 32: 40, 64: 44, 128: 48, 256: 52 })
4666
+ }],
4665
4667
  [16, {
4666
4668
  name: "label_numeric_state",
4667
4669
  read(reader, record, mask) {
@@ -4679,29 +4681,48 @@
4679
4681
  if (mask & 16) record.q36 = (record.q36 || 0) + reader.readFieldDelta();
4680
4682
  }
4681
4683
  }],
4682
- [17, { name: "numeric_sparse", fields: numericFields({ 1: 20, 2: 24, 4: 28, 8: 32, 16: 36 }) }],
4684
+ [17, {
4685
+ name: "ball",
4686
+ packedBeforeValues: true,
4687
+ packedBits: [{ bit: 1, offset: 21 }, { bit: 2, offset: 22 }]
4688
+ }],
4683
4689
  [18, {
4684
4690
  name: "mob_combat_state",
4691
+ // Official reader packs flags 64/2048 before numeric deltas. Raw offsets
4692
+ // follow that reader's layout, rather than treating flag bits as values.
4693
+ packedBeforeValues: true,
4694
+ packedBits: [{ bit: 64, offset: 77 }, { bit: 2048, offset: 78 }],
4695
+ defaults: {
4696
+ q20: -1,
4697
+ q24: 0,
4698
+ q28: 0,
4699
+ q32: 0,
4700
+ q36: 0,
4701
+ q40: -9417217,
4702
+ q44: 0,
4703
+ q48: -100,
4704
+ q52: 0,
4705
+ q56: 10,
4706
+ q60: 10,
4707
+ q64: 1,
4708
+ q68: 1,
4709
+ q72: 100
4710
+ },
4685
4711
  fields: numericFields({
4686
4712
  2: 20,
4687
4713
  4: 24,
4688
4714
  8: 28,
4689
4715
  16: 32,
4690
4716
  32: 36,
4691
- 64: 40,
4692
- 128: 44,
4693
- 256: 48,
4694
- 512: 52,
4695
- 1024: 56,
4696
- 2048: 60,
4697
- 4096: 64,
4698
- 8192: 68,
4699
- 16384: 72,
4700
- 32768: 76,
4701
- 65536: 80,
4702
- 131072: 84,
4703
- 524288: 88,
4704
- 4194304: 92
4717
+ 128: 40,
4718
+ 256: 44,
4719
+ 512: 48,
4720
+ 1024: 52,
4721
+ 4096: 56,
4722
+ 8192: 60,
4723
+ 16384: 64,
4724
+ 32768: 68,
4725
+ 65536: 72
4705
4726
  })
4706
4727
  }],
4707
4728
  [19, { name: "motion_state", packedBits: [{ bit: 4, offset: 29 }], ...TWO_FIELD_SPEC }],
@@ -4755,7 +4776,13 @@
4755
4776
  fields: numericFields({ 1: 20, 2: 24 }),
4756
4777
  blobs: [{ bit: 4, offset: 28 }, { bit: 8, offset: 40 }]
4757
4778
  }],
4758
- [24, { name: "projectile_state", packedBits: [{ bit: 8, offset: 33 }], fields: numericFields({ 1: 20, 2: 24, 4: 28 }) }],
4779
+ [24, {
4780
+ name: "projectile_state",
4781
+ defaults: { q20: 16777215, q24: 1, q28: 1 },
4782
+ packedBeforeValues: true,
4783
+ packedBits: [{ bit: 2, offset: 33 }],
4784
+ fields: numericFields({ 1: 20, 4: 24, 8: 28 })
4785
+ }],
4759
4786
  [25, {
4760
4787
  name: "zone_label",
4761
4788
  orderedValues: true,
@@ -4834,7 +4861,7 @@
4834
4861
  defaults: { q20: 0, q24: 0, q28: 0, q32: 0, q36: 0, q40: 0, q44: 0, q48: 0, q52: 0, q56: 0, q60: 0, q64: 0 },
4835
4862
  fields: numericFields({ 1: 20, 2: 24, 4: 28, 8: 32, 16: 36, 32: 40, 64: 44, 128: 48, 256: 52, 512: 56, 1024: 60, 2048: 64 })
4836
4863
  }],
4837
- [59, { name: "numeric_sparse", fields: numericFields({ 1: 20, 2: 24, 4: 28, 8: 32, 16: 36 }) }],
4864
+ [59, { name: "rcd", fields: numericFields({ 1: 20, 2: 24, 4: 28, 8: 32 }) }],
4838
4865
  [60, { name: "fluid_tank", packedBits: [{ bit: 4, offset: 29 }], ...TWO_FIELD_SPEC }],
4839
4866
  [61, { name: "shield_charge", ...TWO_FIELD_SPEC }],
4840
4867
  [62, { name: "flag_state", packedBits: [{ bit: 1, offset: 21 }], fields: [] }],
@@ -4906,7 +4933,7 @@
4906
4933
  [48, 12],
4907
4934
  [49, 13],
4908
4935
  [50, 14],
4909
- [51, 51],
4936
+ [51, 15],
4910
4937
  [52, 16],
4911
4938
  [74, 17],
4912
4939
  [80, 17],
@@ -5327,38 +5354,113 @@
5327
5354
  combatRecord,
5328
5355
  motionRecord,
5329
5356
  table10Record,
5330
- table51Record,
5357
+ beamRecord,
5331
5358
  itemCrate,
5332
5359
  player,
5333
5360
  shipControl
5334
5361
  }) {
5335
- if (!health || itemCrate || player || shipControl || isBoulderBotExclusion(health, table2Record, combatRecord)) return null;
5362
+ if (!health || itemCrate || player || shipControl) return null;
5336
5363
  const className = botClassFromState({
5337
5364
  health,
5338
5365
  table2Record,
5339
5366
  smallRecord,
5340
5367
  combatRecord,
5341
5368
  table10Record,
5342
- table51Record
5369
+ beamRecord
5343
5370
  });
5371
+ if (className === "bot") return null;
5344
5372
  return {
5345
5373
  entity,
5346
5374
  className,
5375
+ classificationSource: "heuristic",
5376
+ health,
5377
+ beams: summarizeCombatBeams(entity, beamRecord),
5378
+ combat: combatRecord ? {
5379
+ bodyColorRgba: (combatRecord.q20 ?? -1) >>> 0,
5380
+ weaponColorRgba: (combatRecord.q40 ?? -9417217) >>> 0,
5381
+ aimAngle: combatRecord.q44 === -70 ? null : numberOrNull(combatRecord.q44, 10),
5382
+ thrusterMask: combatRecord.q60 ?? 10,
5383
+ alternateSprite: Boolean(combatRecord.q77),
5384
+ beamEffectEnabled: Boolean(combatRecord.q78),
5385
+ state: cloneRecord(combatRecord)
5386
+ } : null,
5347
5387
  identifier: botIdentifierFromState({ combatRecord, motionRecord, smallRecord }),
5348
5388
  typeA: health.state?.q28 ?? null,
5349
5389
  typeB: health.state?.q32 ?? null
5350
5390
  };
5351
5391
  }
5352
- function isBoulderBotExclusion(health, table2Record, combatRecord) {
5353
- return Boolean(
5354
- health?.maxHp === 2e3 && health?.state?.q28 === 30 && health?.state?.q32 != null && table2Record?.q20 != null && table2Record?.q24 == null && !combatRecord
5355
- );
5392
+ function summarizeProjectile(entity, record) {
5393
+ if (!record) return null;
5394
+ const color = record.q20 ?? 16777215;
5395
+ const itemId = record.q28 ?? 1;
5396
+ return {
5397
+ entity,
5398
+ color,
5399
+ colorCss: colorToCss(color),
5400
+ botStyle: Boolean(record.q33),
5401
+ indicatorCount: record.q24 ?? 1,
5402
+ spriteItemId: itemId === 0 ? null : itemId,
5403
+ spriteItemName: itemId === 0 ? null : entityNameFromType(itemId),
5404
+ state: cloneRecord(record)
5405
+ };
5356
5406
  }
5357
- function botClassFromState({ health, table2Record, smallRecord, combatRecord, table10Record, table51Record }) {
5407
+ function summarizeCombatBeams(entity, record) {
5408
+ if (!record) return null;
5409
+ return {
5410
+ entity,
5411
+ beams: [0, 1, 2].map((index) => {
5412
+ const length = (record[qKey(32 + index * 4)] ?? 0) / 10;
5413
+ return {
5414
+ angle: (record[qKey(20 + index * 4)] ?? 0) / 1e3,
5415
+ length,
5416
+ active: length > 0,
5417
+ colorRgba: (record[qKey(44 + index * 4)] ?? 0) >>> 0
5418
+ };
5419
+ }),
5420
+ state: cloneRecord(record)
5421
+ };
5422
+ }
5423
+ function summarizeBall(entity, record, health = null, sizeRecord = null) {
5424
+ if (!record) return null;
5425
+ return {
5426
+ entity,
5427
+ health,
5428
+ radius: numberOrNull(sizeRecord?.q20, 20),
5429
+ rubber: Boolean(record.q21),
5430
+ isEgg: Boolean(record.q22),
5431
+ state: cloneRecord(record)
5432
+ };
5433
+ }
5434
+ function summarizeRcd(entity, record, itemHolderRecord) {
5435
+ if (!record) return null;
5436
+ const variant = (record.q20 ?? 0) === 0 ? "sandbox" : "flux";
5437
+ const item = itemSummary(itemHolderRecord?.q20, itemHolderRecord?.q24);
5438
+ return {
5439
+ entity,
5440
+ variant,
5441
+ variantCode: record.q20 ?? 0,
5442
+ itemId: variant === "sandbox" ? 121 : 122,
5443
+ storedItemId: item.itemId,
5444
+ storedItemName: item.itemName,
5445
+ storedItemCount: item.count,
5446
+ beam: {
5447
+ offsetX: (record.q28 ?? 0) / 5,
5448
+ offsetY: (record.q32 ?? 0) / 5,
5449
+ active: Boolean(record.q28 || record.q32)
5450
+ },
5451
+ state: cloneRecord(record)
5452
+ };
5453
+ }
5454
+ function summarizeRecycler(entity, marker, itemHolderRecord) {
5455
+ if (!marker) return null;
5456
+ const item = itemSummary(itemHolderRecord?.q20, itemHolderRecord?.q24);
5457
+ return { entity, storedItemId: item.itemId, storedItemName: item.itemName, storedItemCount: item.count };
5458
+ }
5459
+ function botClassFromState({ health, table2Record, smallRecord, combatRecord, table10Record, beamRecord }) {
5358
5460
  if (isYellowMineGuardBotState({ health, smallRecord, combatRecord, table2Record })) return "yellow-mine-guard";
5359
5461
  if (isShieldHelperBotState({ health, table2Record })) return "shield-helper";
5360
5462
  if (isShieldMasterBotState({ health, table2Record })) return "shield-master";
5361
- if (isLazerEnthusiastBotState({ health, table2Record, table10Record, table51Record })) return "lazer-enthusiast";
5463
+ if (isLazerEnthusiastBotState({ health, table2Record, table10Record, beamRecord })) return "lazer-enthusiast";
5362
5464
  if (isCowardBossState({ health })) return "the-coward";
5363
5465
  if (isOrangeFoolBotState({ combatRecord })) return "orange-fool";
5364
5466
  if (isZombieBossBotState({ health, table2Record, combatRecord })) return "zombie-boss";
@@ -5372,6 +5474,7 @@
5372
5474
  if (isAquaShielderBotState({ health, table2Record, combatRecord })) return "aqua-shielder";
5373
5475
  if (table2Record) return "table2-bot";
5374
5476
  if (combatRecord) return "combat-bot";
5477
+ if (beamRecord) return "beam-bot";
5375
5478
  return "bot";
5376
5479
  }
5377
5480
  function isCowardBossState({ health }) {
@@ -5398,8 +5501,8 @@
5398
5501
  function isAquaShielderBotState({ health, table2Record, combatRecord }) {
5399
5502
  return combatRecord?.q20 === 13697024 && combatRecord?.q24 === 1 || health?.state?.q28 === 50 && health?.state?.q32 === 122 && table2Record?.q20 === 240 && table2Record?.q24 === -900;
5400
5503
  }
5401
- function isLazerEnthusiastBotState({ health, table2Record, table10Record, table51Record }) {
5402
- return health?.state?.q28 === 140 && health?.state?.q32 === 155 && table2Record?.q20 === 300 && table2Record?.q24 === -900 && Boolean(table10Record) && Boolean(table51Record);
5504
+ function isLazerEnthusiastBotState({ health, table2Record, table10Record, beamRecord }) {
5505
+ return health?.state?.q28 === 140 && health?.state?.q32 === 155 && table2Record?.q20 === 300 && table2Record?.q24 === -900 && Boolean(table10Record) && Boolean(beamRecord);
5403
5506
  }
5404
5507
  function isYellowMineGuardBotState({ health, smallRecord, combatRecord, table2Record }) {
5405
5508
  return health?.state?.q28 === 30 && health?.state?.q32 === 33 && smallRecord?.q20 === 78 && smallRecord?.q24 === 78 && combatRecord?.q24 === -995542016 && !table2Record;
@@ -5952,6 +6055,10 @@
5952
6055
  return { width: 1, height: 1, source: "default" };
5953
6056
  }
5954
6057
  function entityLabel(entity) {
6058
+ if (entity?.projectile) return "Projectile";
6059
+ if (entity?.ball) return entity.ball.isEgg ? "Egg" : "Ball";
6060
+ if (entity?.rcd) return entity.rcd.variant === "sandbox" ? "Sandbox RCD" : "Flux RCD";
6061
+ if (entity?.recycler) return "Recycler";
5955
6062
  if (entity?.category === "metadata" && entity?.typeName) return `Metadata ${entity.typeName}`;
5956
6063
  if (entity?.blueprintPreview) return `Blueprint Preview (${entity.blueprintPreview.itemName ?? entity.blueprintPreview.itemId ?? "item"})`;
5957
6064
  if (entity?.category === "loose_item" && entity?.itemHolder?.itemName) return `Loose ${entity.itemHolder.itemName}`;
@@ -5982,6 +6089,10 @@
5982
6089
  return entity?.typeId != null ? `Entity ${entity.typeId}` : "Entity";
5983
6090
  }
5984
6091
  function entityCategory(entity) {
6092
+ if (entity?.projectile) return "projectile";
6093
+ if (entity?.ball) return "ball";
6094
+ if (entity?.rcd) return "rcd";
6095
+ if (entity?.recycler) return "placed_entity";
5985
6096
  if (entity?.player) return "player";
5986
6097
  if (entity?.blueprintPreview) return "blueprint_preview";
5987
6098
  if (entity?.shipControl) return "ship_control";
@@ -6084,7 +6195,11 @@
6084
6195
  summarizeCommsStation: summarizeCommsStation2,
6085
6196
  summarizeHealth: summarizeHealth2,
6086
6197
  summarizeBot: summarizeBot2,
6087
- isBoulderBotExclusion: isBoulderBotExclusion2,
6198
+ summarizeProjectile: summarizeProjectile2,
6199
+ summarizeCombatBeams: summarizeCombatBeams2,
6200
+ summarizeBall: summarizeBall2,
6201
+ summarizeRcd: summarizeRcd2,
6202
+ summarizeRecycler: summarizeRecycler2,
6088
6203
  botClassFromState: botClassFromState2,
6089
6204
  isCowardBossState: isCowardBossState2,
6090
6205
  isOrangeFoolBotState: isOrangeFoolBotState2,
@@ -6265,6 +6380,11 @@
6265
6380
  blocks: includeBlocks ? this.#derivedBlocks().slice() : void 0,
6266
6381
  transforms: derived.transforms.slice(),
6267
6382
  players: derived.players.slice(),
6383
+ projectiles: derived.specialEntities.projectiles.slice(),
6384
+ bots: derived.specialEntities.bots.slice(),
6385
+ rcds: derived.specialEntities.rcds.slice(),
6386
+ balls: derived.specialEntities.balls.slice(),
6387
+ recyclers: derived.specialEntities.recyclers.slice(),
6268
6388
  shipControls: derived.shipControls.slice(),
6269
6389
  machines: this.#machinesSnapshot(derived.machines),
6270
6390
  tables: includeTables ? this.tablesSnapshot() : derived.tableSummaries.slice()
@@ -6289,6 +6409,21 @@
6289
6409
  players() {
6290
6410
  return this.#derivedState().players.slice();
6291
6411
  }
6412
+ projectiles() {
6413
+ return this.#derivedState().specialEntities.projectiles.slice();
6414
+ }
6415
+ bots() {
6416
+ return this.#derivedState().specialEntities.bots.slice();
6417
+ }
6418
+ rcds() {
6419
+ return this.#derivedState().specialEntities.rcds.slice();
6420
+ }
6421
+ balls() {
6422
+ return this.#derivedState().specialEntities.balls.slice();
6423
+ }
6424
+ recyclers() {
6425
+ return this.#derivedState().specialEntities.recyclers.slice();
6426
+ }
6292
6427
  shipControls() {
6293
6428
  return this.#derivedState().shipControls.slice();
6294
6429
  }
@@ -6633,6 +6768,7 @@
6633
6768
  doors: [],
6634
6769
  expandoBoxes: []
6635
6770
  };
6771
+ const specialEntities = { projectiles: [], bots: [], rcds: [], balls: [], recyclers: [] };
6636
6772
  const players = [];
6637
6773
  const shipControls = [];
6638
6774
  const transforms = [];
@@ -6661,12 +6797,18 @@
6661
6797
  if (contents.spawnPoint) machines.spawnPoints.push(contents.spawnPoint);
6662
6798
  if (contents.door) machines.doors.push(contents.door);
6663
6799
  if (contents.expandoBox) machines.expandoBoxes.push(contents.expandoBox);
6800
+ if (contents.projectile) specialEntities.projectiles.push(contents.projectile);
6801
+ if (contents.bot) specialEntities.bots.push(contents.bot);
6802
+ if (contents.rcd) specialEntities.rcds.push(contents.rcd);
6803
+ if (contents.ball) specialEntities.balls.push(contents.ball);
6804
+ if (contents.recycler) specialEntities.recyclers.push(contents.recycler);
6664
6805
  if (contents.player) players.push(contents.player);
6665
6806
  if (contents.shipControl) shipControls.push(contents.shipControl);
6666
6807
  }
6667
6808
  derived.entities = entities;
6668
6809
  derived.transforms = transforms;
6669
6810
  derived.players = players;
6811
+ derived.specialEntities = specialEntities;
6670
6812
  derived.shipControls = shipControls;
6671
6813
  derived.machines = machines;
6672
6814
  derived.summariesDirty = false;
@@ -6743,6 +6885,11 @@
6743
6885
  const itemHolder = summarizeItemHolder2(entityId, itemHolderRecord);
6744
6886
  const isExpandoBox = typeId === EXPANDO_BOX_TYPE_ID2 || markerTypeId === EXPANDO_BOX_TYPE_ID2;
6745
6887
  const health = summarizeHealth2(entityId, healthRecord);
6888
+ const projectile = summarizeProjectile2(entityId, rec(24));
6889
+ const combatBeams = summarizeCombatBeams2(entityId, rec(15));
6890
+ const ball = summarizeBall2(entityId, rec(17), health, rec(2));
6891
+ const rcd = summarizeRcd2(entityId, rec(59), itemHolderRecord);
6892
+ const recycler = this.isOverworld === false ? summarizeRecycler2(entityId, rec(23), itemHolderRecord) : null;
6746
6893
  const fabricator = summarizeFabricator2(entityId, fabricatorRecord, itemHolderRecord, typeRecord);
6747
6894
  const cargoEjector = summarizeCargoEjector2(entityId, typeId, cargoEjectorRecord);
6748
6895
  const cannon = summarizeCannon2(entityId, cannonRecord, typeId, transformRecord);
@@ -6774,15 +6921,15 @@
6774
6921
  const mapMarker = this.isOverworld ? summarizeMapMarker2(entityId, labelRecord, zoneLabelRecord, crateSizeRecord) : null;
6775
6922
  const dockingSpring = this.isOverworld ? summarizeDockingSpring2(entityId, dockingSpringRecord, bodyStateRecord, crateSizeRecord) : null;
6776
6923
  const hugeThruster = this.isOverworld ? summarizeHugeThruster2(entityId, hugeThrusterRecord, crateSizeRecord) : null;
6777
- const itemCrate = this.isOverworld && !rec(2) && !rec(18) && health && crateSizeRecord ? summarizeItemCrate2(entityId, crateSizeRecord, crateItemRecord, healthRecord) : null;
6778
- const bot = this.isOverworld ? summarizeBot2(entityId, {
6924
+ const itemCrate = this.isOverworld && !rec(2) && !rec(18) && !combatBeams && !projectile && !ball && !rcd && health && crateSizeRecord ? summarizeItemCrate2(entityId, crateSizeRecord, crateItemRecord, healthRecord) : null;
6925
+ const bot = (this.isOverworld || rec(18) || combatBeams) && !projectile && !ball && !rcd ? summarizeBot2(entityId, {
6779
6926
  health,
6780
6927
  table2Record: rec(2),
6781
6928
  smallRecord: crateSizeRecord,
6782
6929
  combatRecord: rec(18),
6783
6930
  motionRecord: crateItemRecord,
6784
6931
  table10Record: rec(10),
6785
- table51Record: rec(51),
6932
+ beamRecord: rec(15),
6786
6933
  itemCrate,
6787
6934
  player,
6788
6935
  shipControl
@@ -6795,6 +6942,11 @@
6795
6942
  flags: [transformRecord.q33, transformRecord.q34, transformRecord.q35].filter((value) => value != null)
6796
6943
  } : null;
6797
6944
  const contents = mergeContents2({
6945
+ projectile,
6946
+ combatBeams,
6947
+ ball,
6948
+ rcd,
6949
+ recycler,
6798
6950
  itemHolder,
6799
6951
  expandoBox,
6800
6952
  hoverOutline,
@@ -6855,6 +7007,10 @@
6855
7007
  });
6856
7008
  const typeName = entityNameFromType2(typeId);
6857
7009
  const category = entityCategory2({
7010
+ projectile,
7011
+ ball,
7012
+ rcd,
7013
+ recycler,
6858
7014
  typeId,
6859
7015
  markerTypeId,
6860
7016
  looseItemMarker,
@@ -6890,6 +7046,10 @@
6890
7046
  markerTypeId,
6891
7047
  markerTypeName,
6892
7048
  label: entityLabel2({
7049
+ projectile,
7050
+ ball,
7051
+ rcd,
7052
+ recycler,
6893
7053
  category,
6894
7054
  typeId,
6895
7055
  typeName,
@@ -6923,6 +7083,11 @@
6923
7083
  isOverworld: this.isOverworld
6924
7084
  }),
6925
7085
  kind: [
7086
+ projectile ? "projectile" : null,
7087
+ combatBeams ? "combat_beams" : null,
7088
+ ball ? "ball" : null,
7089
+ rcd ? "rcd" : null,
7090
+ recycler ? "recycler" : null,
6926
7091
  transform ? "transform" : null,
6927
7092
  dynamicBody ? "dynamic_body" : null,
6928
7093
  itemHolder ? "item_holder" : null,
@@ -7529,6 +7694,11 @@
7529
7694
  transforms: model.transforms,
7530
7695
  machines: model.machines,
7531
7696
  players: model.players,
7697
+ projectiles: model.projectiles,
7698
+ bots: model.bots,
7699
+ rcds: model.rcds,
7700
+ balls: model.balls,
7701
+ recyclers: model.recyclers,
7532
7702
  shipControls: model.shipControls,
7533
7703
  commsBubbles: this.commsBubbles.slice(),
7534
7704
  tiles: includeTiles ? [...this.tiles.values()] : void 0
@@ -8941,6 +9111,11 @@
8941
9111
  this.entities = new EntityCollection(client, scope);
8942
9112
  this.machines = new MachineCollection(client, scope);
8943
9113
  this.players = new PlayerCollection(client, scope);
9114
+ this.projectiles = new EntitySummaryCollection(client, scope, "projectiles");
9115
+ this.bots = new EntitySummaryCollection(client, scope, "bots");
9116
+ this.rcds = new EntitySummaryCollection(client, scope, "rcds");
9117
+ this.balls = new EntitySummaryCollection(client, scope, "balls");
9118
+ this.recyclers = new EntitySummaryCollection(client, scope, "recyclers");
8944
9119
  this.blocks = new BlockCollection(client, scope);
8945
9120
  this.materials = new MaterialCollection(client, scope);
8946
9121
  }
@@ -9058,6 +9233,21 @@
9058
9233
  return currentPlayerSummary(this.client, this.scope);
9059
9234
  }
9060
9235
  };
9236
+ var EntitySummaryCollection = class {
9237
+ constructor(client, scope, method) {
9238
+ this.client = client;
9239
+ this.scope = scope;
9240
+ this.method = method;
9241
+ this.component = { projectiles: "projectile", bots: "bot", rcds: "rcd", balls: "ball", recyclers: "recycler" }[method];
9242
+ }
9243
+ all() {
9244
+ return worldStateFor(this.client, this.scope)?.model[this.method]() || [];
9245
+ }
9246
+ get(entity) {
9247
+ const id = entityIdOf(entity);
9248
+ return worldStateFor(this.client, this.scope)?.model.entity(id)?.contents?.[this.component] || null;
9249
+ }
9250
+ };
9061
9251
  var BlockCollection = class {
9062
9252
  constructor(client, scope) {
9063
9253
  this.client = client;
@@ -9709,6 +9899,7 @@
9709
9899
  }
9710
9900
  };
9711
9901
  var ENTITY_COMPONENT_ALIASES = /* @__PURE__ */ new Map([
9902
+ ["combatbeams", "combatBeams"],
9712
9903
  ["hoveroutline", "hoverOutline"],
9713
9904
  ["outline", "hoverOutline"],
9714
9905
  ["itemholder", "itemHolder"],
@@ -9759,6 +9950,12 @@
9759
9950
  "expandoBox"
9760
9951
  ];
9761
9952
  var ENTITY_FEATURES = [
9953
+ "combatBeams",
9954
+ "projectile",
9955
+ "bot",
9956
+ "rcd",
9957
+ "ball",
9958
+ "recycler",
9762
9959
  "health",
9763
9960
  "position",
9764
9961
  "outline",
@@ -9817,6 +10014,10 @@
9817
10014
  return null;
9818
10015
  }
9819
10016
  function entityPublicType(summary, contents) {
10017
+ if (contents?.projectile) return "projectile";
10018
+ if (contents?.rcd) return "rcd";
10019
+ if (contents?.ball) return contents.ball.isEgg ? "egg" : "ball";
10020
+ if (contents?.recycler) return "recycler";
9820
10021
  const machine = entityMachineType(contents);
9821
10022
  if (machine) return machine;
9822
10023
  if (contents?.player || summary?.category === "player") return "player";