dredless 0.6.3 → 0.7.0

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.
@@ -3895,7 +3895,6 @@
3895
3895
  SHIELD_GENERATOR_BOOST_STATE_NAMES: () => SHIELD_GENERATOR_BOOST_STATE_NAMES,
3896
3896
  SIGN_DISPLAY_MODE_NAMES: () => SIGN_DISPLAY_MODE_NAMES,
3897
3897
  SIMPLE_LABEL_STATE_SPEC: () => SIMPLE_LABEL_STATE_SPEC,
3898
- TABLE_78_FIELD_BITS: () => TABLE_78_FIELD_BITS,
3899
3898
  TABLE_78_NUMERIC_FIELDS: () => TABLE_78_NUMERIC_FIELDS,
3900
3899
  TEAM_RANK_NAMES: () => TEAM_RANK_NAMES,
3901
3900
  THRUSTER_FACING_NAMES: () => THRUSTER_FACING_NAMES,
@@ -3928,7 +3927,6 @@
3928
3927
  isOrangeFoolBotState: () => isOrangeFoolBotState,
3929
3928
  isRedSentryBotState: () => isRedSentryBotState,
3930
3929
  isRedSniperBotState: () => isRedSniperBotState,
3931
- isSemanticLoaderDelta: () => isSemanticLoaderDelta2,
3932
3930
  isShieldHelperBotState: () => isShieldHelperBotState,
3933
3931
  isShieldMasterBotState: () => isShieldMasterBotState,
3934
3932
  isYellowHunterBotState: () => isYellowHunterBotState,
@@ -3980,8 +3978,7 @@
3980
3978
  summarizeShipWorldMetadata: () => summarizeShipWorldMetadata,
3981
3979
  summarizeSign: () => summarizeSign,
3982
3980
  summarizeSpawnPoint: () => summarizeSpawnPoint,
3983
- summarizeThruster: () => summarizeThruster,
3984
- table78DeltaRecord: () => table78DeltaRecord
3981
+ summarizeThruster: () => summarizeThruster
3985
3982
  });
3986
3983
  init_constants();
3987
3984
 
@@ -4007,858 +4004,6 @@
4007
4004
  [2, "allow-filter"],
4008
4005
  [3, "block-all"]
4009
4006
  ]);
4010
- var DEFAULT_LOADER_PRIORITY = 0;
4011
- var DEFAULT_LOADER_FILTER_MODE = 0;
4012
- var DEFAULT_LOADER_STACK = 16;
4013
- var DEFAULT_LOADER_CYCLE = 1;
4014
- var DEFAULT_LOADER_PICK = 3;
4015
- var DEFAULT_LOADER_PLACE = 4;
4016
- var LOADER_CONFIG_NUMERIC_BITS = [1, 2, 4, 8, 16];
4017
- var LOADER_CONFIG_NUMERIC_FIELDS = ["q20", "q24", "q28", "q32", "q36"];
4018
- function wrapLoaderPosition(value) {
4019
- return value == null ? null : (value % 8 + 8) % 8;
4020
- }
4021
- function decodeIndexedLoaderSnapshotRecord(loader, mask = 0, cumulative = null, reference = null) {
4022
- const config = {
4023
- pick: 3,
4024
- place: 4,
4025
- priority: DEFAULT_LOADER_PRIORITY,
4026
- requireOutput: false,
4027
- waitForStack: false,
4028
- stack: DEFAULT_LOADER_STACK,
4029
- cycle: DEFAULT_LOADER_CYCLE
4030
- };
4031
- if (mask & 32) config.requireOutput = true;
4032
- if (mask & 64) config.waitForStack = true;
4033
- switch (mask) {
4034
- case 0:
4035
- break;
4036
- case 1:
4037
- config.pick = wrapLoaderPosition((loader.q20 ?? 0) + 3);
4038
- if (cumulative?.q40 != null) config.requireOutput = true;
4039
- break;
4040
- case 2:
4041
- if (reference && cumulative?.q40 != null && loader.q24 != null) {
4042
- if (loader.q24 <= -8) {
4043
- config.pick = wrapLoaderPosition((reference.pick ?? 3) + 1);
4044
- config.place = wrapLoaderPosition((reference.place ?? 4) + 3);
4045
- config.requireOutput = true;
4046
- } else {
4047
- config.pick = wrapLoaderPosition((reference.pick ?? 3) + 2);
4048
- config.place = wrapLoaderPosition((reference.place ?? 4) + 4);
4049
- }
4050
- } else {
4051
- config.place = wrapLoaderPosition((loader.q24 ?? 0) + 4);
4052
- }
4053
- break;
4054
- case 3:
4055
- config.pick = reference && loader.q24 <= -8 ? wrapLoaderPosition((reference.pick ?? 3) + (loader.q20 ?? 0) + 3) : wrapLoaderPosition((loader.q20 ?? 0) + 3);
4056
- config.place = wrapLoaderPosition((loader.q24 ?? 0) + 4);
4057
- if (cumulative?.q44 != null && cumulative?.q36 == null && cumulative?.q40 == null) {
4058
- config.requireOutput = true;
4059
- config.waitForStack = true;
4060
- }
4061
- break;
4062
- case 5:
4063
- config.pick = wrapLoaderPosition((loader.q28 ?? 0) + 1);
4064
- config.place = wrapLoaderPosition((loader.q28 ?? 0) + 3);
4065
- break;
4066
- case 6:
4067
- config.pick = wrapLoaderPosition((loader.q24 ?? 0) + 5);
4068
- config.place = wrapLoaderPosition((loader.q24 ?? 0) + 3);
4069
- config.requireOutput = true;
4070
- break;
4071
- case 7:
4072
- if (reference && (cumulative?.q40 != null || loader.q24 <= -8 || loader.q28 >= 2)) {
4073
- if (loader.q24 <= -8) {
4074
- config.pick = wrapLoaderPosition((reference.pick ?? 3) + (loader.q20 ?? 0) + 5);
4075
- config.place = wrapLoaderPosition(reference.place ?? 4);
4076
- config.requireOutput = true;
4077
- config.waitForStack = true;
4078
- if (loader.q28 != null) config.priority = loader.q28;
4079
- } else if (loader.q28 >= 2) {
4080
- config.pick = wrapLoaderPosition((reference.pick ?? 3) + loader.q28);
4081
- config.place = wrapLoaderPosition((reference.place ?? 4) + (loader.q20 ?? 0));
4082
- config.priority = loader.q28 - 4;
4083
- } else if ((loader.q20 ?? 0) >= 3) {
4084
- config.pick = wrapLoaderPosition((reference.pick ?? 3) + (loader.q20 ?? 0));
4085
- config.place = wrapLoaderPosition(reference.place ?? 4);
4086
- config.priority = (loader.q28 ?? 0) + 1;
4087
- config.requireOutput = Boolean(reference.requireOutput);
4088
- config.waitForStack = Boolean(reference.waitForStack);
4089
- } else {
4090
- config.pick = wrapLoaderPosition((loader.q20 ?? 0) + 2);
4091
- config.place = wrapLoaderPosition((reference.place ?? 4) + (loader.q24 ?? 0));
4092
- config.priority = (loader.q28 ?? 0) + 1;
4093
- }
4094
- } else {
4095
- config.pick = wrapLoaderPosition((loader.q20 ?? 0) + 3);
4096
- config.place = wrapLoaderPosition((loader.q24 ?? 0) + 4);
4097
- if (loader.q28 != null) config.priority = loader.q28;
4098
- }
4099
- break;
4100
- case 8:
4101
- config.pick = wrapLoaderPosition((cumulative?.q40 ?? 0) + 4);
4102
- config.place = wrapLoaderPosition((cumulative?.q28 ?? 0) + 2);
4103
- config.requireOutput = true;
4104
- break;
4105
- case 9:
4106
- config.pick = wrapLoaderPosition((loader.q20 ?? 0) + 3);
4107
- config.place = wrapLoaderPosition((cumulative?.q40 ?? 0) + 3);
4108
- break;
4109
- case 18:
4110
- config.pick = wrapLoaderPosition(loader.q24 ?? 0);
4111
- config.place = wrapLoaderPosition((loader.q36 ?? 0) + 2);
4112
- if (loader.q36 != null) config.cycle = loader.q36 / 20 + 1;
4113
- break;
4114
- case 32:
4115
- break;
4116
- case 65:
4117
- config.pick = wrapLoaderPosition((loader.q44 ?? 0) + 3);
4118
- break;
4119
- case 33:
4120
- config.pick = wrapLoaderPosition((loader.q40 ?? 0) + 3);
4121
- config.place = wrapLoaderPosition((loader.q20 ?? 0) + 4);
4122
- break;
4123
- case 34:
4124
- config.pick = wrapLoaderPosition((loader.q24 ?? 0) + 3);
4125
- config.place = wrapLoaderPosition((loader.q40 ?? 0) + 4);
4126
- break;
4127
- case 35:
4128
- config.pick = wrapLoaderPosition((loader.q24 ?? 0) + 3);
4129
- config.place = wrapLoaderPosition((loader.q40 ?? 0) + 4);
4130
- break;
4131
- case 67:
4132
- config.pick = wrapLoaderPosition((loader.q24 ?? 0) + 3);
4133
- config.place = wrapLoaderPosition((loader.q44 ?? 0) + 4);
4134
- break;
4135
- case 95:
4136
- config.pick = wrapLoaderPosition((loader.q24 ?? 0) + 3);
4137
- config.place = wrapLoaderPosition((loader.q28 ?? 0) + 4);
4138
- if (loader.q32 != null) config.priority = loader.q32;
4139
- if (loader.q36 != null) config.stack = DEFAULT_LOADER_STACK + loader.q36;
4140
- if (loader.q44 != null) config.cycle = loader.q44 / 20 + 1;
4141
- break;
4142
- case 98:
4143
- config.place = wrapLoaderPosition((loader.q40 ?? 0) + 4);
4144
- break;
4145
- case 99:
4146
- config.pick = wrapLoaderPosition((loader.q24 ?? 0) + 3);
4147
- config.place = wrapLoaderPosition((loader.q40 ?? 0) + 4);
4148
- break;
4149
- case 126:
4150
- config.pick = wrapLoaderPosition(loader.q28 ?? 0);
4151
- config.place = wrapLoaderPosition(loader.q24 ?? 0);
4152
- if (loader.q32 != null) config.priority = loader.q32;
4153
- if (loader.q36 != null) config.stack = DEFAULT_LOADER_STACK + loader.q36;
4154
- if (loader.q40 != null) config.cycle = loader.q40 / 20 + 1;
4155
- break;
4156
- default:
4157
- return null;
4158
- }
4159
- return config;
4160
- }
4161
- function decodeLoaderSnapshotRecord(loader, mask = loader?.lastMask ?? 0) {
4162
- if (!loader) return null;
4163
- const hasRequireOutput = Boolean(mask & 32);
4164
- const hasWaitForStack = Boolean(mask & 64);
4165
- const hasFlag = hasRequireOutput || hasWaitForStack;
4166
- const slots = [];
4167
- for (const [index, bit] of LOADER_CONFIG_NUMERIC_BITS.entries()) {
4168
- if (!(mask & bit)) continue;
4169
- const value = loader[LOADER_CONFIG_NUMERIC_FIELDS[index]];
4170
- if (value == null) return null;
4171
- slots.push(value);
4172
- }
4173
- if (hasRequireOutput) {
4174
- if (loader.q40 == null) return null;
4175
- slots.push(loader.q40);
4176
- } else if (hasWaitForStack) {
4177
- if (loader.q44 == null) return null;
4178
- slots.push(loader.q44);
4179
- }
4180
- if (hasFlag && slots.length) slots.shift();
4181
- const config = {
4182
- pick: 3,
4183
- place: 4,
4184
- priority: DEFAULT_LOADER_PRIORITY,
4185
- requireOutput: hasRequireOutput,
4186
- waitForStack: hasWaitForStack,
4187
- stack: DEFAULT_LOADER_STACK,
4188
- cycle: DEFAULT_LOADER_CYCLE
4189
- };
4190
- if (mask & 1) {
4191
- if (!slots.length) return null;
4192
- config.pick = wrapLoaderPosition(slots.shift() + 3);
4193
- }
4194
- if (mask & 2) {
4195
- if (!slots.length) return null;
4196
- config.place = wrapLoaderPosition(slots.shift() + 4);
4197
- }
4198
- if (mask & 4) {
4199
- if (!slots.length) return null;
4200
- config.priority = slots.shift();
4201
- }
4202
- if (mask & 8) {
4203
- if (!slots.length) return null;
4204
- config.stack = DEFAULT_LOADER_STACK + slots.shift();
4205
- }
4206
- if (mask & 16) {
4207
- if (!slots.length) return null;
4208
- config.cycle = slots.shift() / 20 + 1;
4209
- }
4210
- return config;
4211
- }
4212
- function decodeLoaderSemanticDeltaRecord(loader, mask = loader?.lastMask ?? 0) {
4213
- if (!loader) return null;
4214
- const hasRequireOutput = Boolean(mask & 32);
4215
- const hasWaitForStack = Boolean(mask & 64);
4216
- if (!hasRequireOutput && !hasWaitForStack) return null;
4217
- const slots = [];
4218
- for (const [index, bit] of LOADER_CONFIG_NUMERIC_BITS.entries()) {
4219
- if (!(mask & bit)) continue;
4220
- slots.push(loader[LOADER_CONFIG_NUMERIC_FIELDS[index]] ?? 0);
4221
- }
4222
- if (hasRequireOutput) slots.push(loader.q40 ?? 0);
4223
- else if (hasWaitForStack) slots.push(loader.q44 ?? 0);
4224
- if (slots.length) slots.shift();
4225
- const config = {};
4226
- if (mask & 1) config.pick = slots.shift() ?? 0;
4227
- if (mask & 2) config.place = slots.shift() ?? 0;
4228
- if (mask & 4) config.priority = slots.shift() ?? 0;
4229
- if (mask & 8) config.stack = slots.shift() ?? 0;
4230
- if (mask & 16) config.cycleTicks = slots.shift() ?? 0;
4231
- config.requireOutput = hasRequireOutput;
4232
- config.waitForStack = hasWaitForStack;
4233
- return config;
4234
- }
4235
- function loaderDeltaRecord(loader, mask, previous) {
4236
- const record = { lastMask: mask };
4237
- for (const [field, bit] of [
4238
- ["q20", 1],
4239
- ["q24", 2],
4240
- ["q28", 4],
4241
- ["q32", 8],
4242
- ["q36", 16],
4243
- ["q40", 32],
4244
- ["q44", 64]
4245
- ]) {
4246
- if (!(mask & bit)) continue;
4247
- if (field === "q44" && (mask & 32 || loader?.q44 == null)) continue;
4248
- record[field] = (loader?.[field] ?? 0) - (previous?.[field] ?? 0);
4249
- }
4250
- return record;
4251
- }
4252
- function isSemanticLoaderDelta(changed, full) {
4253
- return !full && changed.previous != null && (changed.mask & 96) === 96;
4254
- }
4255
- function filterSlotValue(value) {
4256
- return value == null || value === 0 ? null : value;
4257
- }
4258
- var LoaderConfigTracker = class {
4259
- constructor() {
4260
- this.pickBases = /* @__PURE__ */ new Map();
4261
- this.pickDeltaBases = /* @__PURE__ */ new Map();
4262
- this.placeBases = /* @__PURE__ */ new Map();
4263
- this.placeDeltaBases = /* @__PURE__ */ new Map();
4264
- this.currentPicks = /* @__PURE__ */ new Map();
4265
- this.currentPlaces = /* @__PURE__ */ new Map();
4266
- this.sparsePositionBaselines = /* @__PURE__ */ new Set();
4267
- this.priorities = /* @__PURE__ */ new Map();
4268
- this.priorityOffsets = /* @__PURE__ */ new Map();
4269
- this.filterModes = /* @__PURE__ */ new Map();
4270
- this.filterSources = /* @__PURE__ */ new Map();
4271
- this.requireOutputs = /* @__PURE__ */ new Map();
4272
- this.waitForStacks = /* @__PURE__ */ new Map();
4273
- this.stackBases = /* @__PURE__ */ new Map();
4274
- this.stackSources = /* @__PURE__ */ new Map();
4275
- this.cycles = /* @__PURE__ */ new Map();
4276
- this.cycleModes = /* @__PURE__ */ new Map();
4277
- this.cycleDeltaBases = /* @__PURE__ */ new Map();
4278
- this.directCycleValues = /* @__PURE__ */ new Map();
4279
- this.directCycleFields = /* @__PURE__ */ new Map();
4280
- }
4281
- updateFromModel(update) {
4282
- const world = update?.world;
4283
- const model = update?.result?.model;
4284
- if (!world || !model) return;
4285
- const seenEntities = /* @__PURE__ */ new Set();
4286
- for (const section of model.sections || []) {
4287
- if (section.table !== 78) continue;
4288
- for (const changed of section.records || []) {
4289
- if (changed.indexedLoaderConfig) {
4290
- this.updateIndexedSnapshotRecord(world.id, changed.entity, changed.record, changed.mask, changed.cumulativeRecord, changed.configEntity);
4291
- continue;
4292
- }
4293
- const loader = changed.record ?? world.model.record(78, changed.entity);
4294
- this.updateRecord(world.id, changed.entity, loader, changed.mask, changed.previous, {
4295
- repeatedInUpdate: seenEntities.has(changed.entity),
4296
- repeatedInSection: changed.repeatedInSection,
4297
- semanticSnapshot: Boolean(model.full),
4298
- semanticDelta: isSemanticLoaderDelta(changed, model.full),
4299
- deltaRecord: loaderDeltaRecord(loader, changed.mask, changed.previous)
4300
- });
4301
- seenEntities.add(changed.entity);
4302
- }
4303
- }
4304
- }
4305
- updateRecord(worldId, entityId, loader, mask = 0, previous = null, options = {}) {
4306
- if (!loader) return;
4307
- const key = this.#key(worldId, entityId);
4308
- const hasTrackedConfig = this.#hasTrackedConfig(key);
4309
- if (hasTrackedConfig && (options.repeatedInSection || options.repeatedInUpdate) && this.sparsePositionBaselines.has(key) && this.hasPositionConfig(worldId, entityId)) {
4310
- return;
4311
- }
4312
- if (!hasTrackedConfig && this.#isDirectPositionCycleBaseline(loader, mask)) {
4313
- this.pickBases.set(key, 3);
4314
- this.pickDeltaBases.set(key, 0);
4315
- this.placeBases.set(key, 4);
4316
- this.placeDeltaBases.set(key, 0);
4317
- this.#setCurrentPosition(key, loader);
4318
- if (mask & 4 && loader.q28 >= -1 && loader.q28 <= 1) this.priorities.set(key, loader.q28);
4319
- this.requireOutputs.set(key, Boolean(mask & 32));
4320
- this.waitForStacks.set(key, Boolean(mask & 64));
4321
- this.stackBases.set(key, 16);
4322
- this.stackSources.delete(key);
4323
- this.cycleModes.set(key, "direct");
4324
- this.cycleDeltaBases.set(key, 0);
4325
- this.directCycleValues.set(key, loader.q44 ?? loader.q36);
4326
- this.directCycleFields.set(key, loader.q44 == null ? "q36" : "q44");
4327
- this.cycles.set(key, (loader.q44 ?? loader.q36) / 20 + 1);
4328
- return;
4329
- }
4330
- if (!hasTrackedConfig && options.allowSparseBaseline && this.#isSparsePositionBaseline(loader, mask)) {
4331
- this.#applySparsePositionBaseline(key, loader, mask);
4332
- return;
4333
- }
4334
- const baseline = hasTrackedConfig ? null : this.#loaderBaseline(loader, mask, options.semanticSnapshot);
4335
- if (hasTrackedConfig && options.semanticDelta && this.#applySemanticDelta(worldId, entityId, loader, mask, previous, options.deltaRecord)) {
4336
- return;
4337
- }
4338
- const hasInitialConfigFields = baseline || mask & 31 && (mask & 32 || mask & 64 && mask & 4);
4339
- if (!hasTrackedConfig && hasInitialConfigFields && mask !== 32 && mask !== 64) {
4340
- if (baseline) this.#applyLoaderBaseline(key, loader, baseline);
4341
- else {
4342
- const usedQ28AsPositionBase = this.#initializePositionBaseline(key, loader, mask);
4343
- if (mask & 4 && loader.q28 != null) {
4344
- if (usedQ28AsPositionBase) this.#initializePriorityOffset(key, loader);
4345
- else this.priorities.set(key, loader.q28);
4346
- }
4347
- }
4348
- this.requireOutputs.set(key, Boolean(mask & 32));
4349
- this.waitForStacks.set(key, Boolean(mask & 64));
4350
- if (!this.stackBases.has(key)) this.#initializeStackBaseline(key, loader);
4351
- if (!this.cycles.has(key)) this.#initializeCycleBaseline(key, loader);
4352
- return;
4353
- }
4354
- const q44CycleChanged = mask & 64 && this.#usesQ44CycleBase(key) && loader.q44 != null && (this.#fieldChanged(previous, loader, "q44") || this.directCycleValues.has(key) && loader.q44 !== this.directCycleValues.get(key));
4355
- const q40DirectCycleChanged = mask & 32 && this.cycleModes.get(key) === "q40-direct" && loader.q40 != null && (this.#fieldChanged(previous, loader, "q40") || this.directCycleValues.has(key) && loader.q40 !== this.directCycleValues.get(key));
4356
- if (q44CycleChanged) {
4357
- this.directCycleValues.set(key, loader.q44);
4358
- this.#updateCycle(key, loader);
4359
- } else if (q40DirectCycleChanged) {
4360
- this.directCycleValues.set(key, loader.q40);
4361
- this.#updateCycle(key, loader);
4362
- } else if (mask & 32 && mask === 32) {
4363
- this.requireOutputs.set(key, !this.requireOutputs.get(key));
4364
- } else if (mask & 32 && !this.requireOutputs.has(key)) {
4365
- this.requireOutputs.set(key, true);
4366
- }
4367
- if (!q44CycleChanged) {
4368
- if (mask & 64 && mask === 64) this.waitForStacks.set(key, !this.waitForStacks.get(key));
4369
- else if (mask & 64 && !this.waitForStacks.has(key)) this.waitForStacks.set(key, true);
4370
- }
4371
- if (mask & 4 && loader.q28 != null) this.priorities.set(key, this.#priority(key, loader.q28));
4372
- if (mask & 8 && this.filterSources.get(key) === "q32" && loader.q32 != null) this.filterModes.set(key, loader.q32);
4373
- const q32FilterOnlyUpdate = this.filterSources.get(key) === "q32" && mask === 8;
4374
- if (mask & 8 && !options.semanticDelta && !q32FilterOnlyUpdate && loader.q32 != null && this.stackBases.has(key)) {
4375
- const previousConfig = this.getConfig(worldId, entityId, previous);
4376
- this.stackBases.set(key, previousConfig.stack - (previous?.q32 ?? 0));
4377
- this.stackSources.set(key, "q32");
4378
- }
4379
- if (mask & 16) this.#updateCycle(key, loader);
4380
- if (mask & 3 && this.hasPositionConfig(worldId, entityId)) this.#setCurrentPosition(key, loader);
4381
- }
4382
- updateIndexedSnapshotRecord(worldId, entityId, loader, mask = 0, cumulative = null, configEntity = null) {
4383
- if (!loader) return false;
4384
- const reference = configEntity == null || Number(configEntity) === Number(entityId) ? null : this.#trackedConfig(worldId, configEntity);
4385
- const config = decodeIndexedLoaderSnapshotRecord(loader, mask, cumulative, reference);
4386
- if (!config) return false;
4387
- const key = this.#key(worldId, entityId);
4388
- this.pickBases.set(key, config.pick);
4389
- this.pickDeltaBases.set(key, loader.q20 ?? 0);
4390
- this.placeBases.set(key, config.place);
4391
- this.placeDeltaBases.set(key, loader.q24 ?? 0);
4392
- this.currentPicks.set(key, config.pick);
4393
- this.currentPlaces.set(key, config.place);
4394
- this.sparsePositionBaselines.delete(key);
4395
- this.priorities.set(key, config.priority);
4396
- if (mask === 95 && loader.q28 != null) this.priorityOffsets.set(key, config.priority - loader.q28);
4397
- else this.priorityOffsets.delete(key);
4398
- this.filterModes.delete(key);
4399
- this.filterSources.delete(key);
4400
- this.requireOutputs.set(key, config.requireOutput);
4401
- this.waitForStacks.set(key, config.waitForStack);
4402
- this.stackBases.set(key, config.stack - (loader.q32 ?? 0));
4403
- this.stackSources.delete(key);
4404
- this.cycles.set(key, config.cycle);
4405
- if (mask === 95) {
4406
- this.cycleModes.set(key, "q44-q36-delta");
4407
- this.cycleDeltaBases.set(key, loader.q36 ?? 0);
4408
- this.directCycleValues.set(key, loader.q44);
4409
- this.directCycleFields.set(key, "q44");
4410
- } else if (mask === 126) {
4411
- this.cycleModes.set(key, "offset");
4412
- this.cycleDeltaBases.set(key, loader.q36 ?? 0);
4413
- this.directCycleValues.delete(key);
4414
- this.directCycleFields.delete(key);
4415
- } else {
4416
- this.cycleModes.set(key, "direct");
4417
- this.cycleDeltaBases.set(key, 0);
4418
- }
4419
- if (loader.q36 != null && mask === 18) {
4420
- this.directCycleValues.set(key, loader.q36);
4421
- this.directCycleFields.set(key, "q36");
4422
- } else if (mask !== 95 && mask !== 126) {
4423
- this.directCycleValues.delete(key);
4424
- this.directCycleFields.delete(key);
4425
- }
4426
- return true;
4427
- }
4428
- delete(worldId, entityId) {
4429
- const key = this.#key(worldId, entityId);
4430
- this.pickBases.delete(key);
4431
- this.pickDeltaBases.delete(key);
4432
- this.placeBases.delete(key);
4433
- this.placeDeltaBases.delete(key);
4434
- this.currentPicks.delete(key);
4435
- this.currentPlaces.delete(key);
4436
- this.sparsePositionBaselines.delete(key);
4437
- this.priorities.delete(key);
4438
- this.priorityOffsets.delete(key);
4439
- this.filterModes.delete(key);
4440
- this.filterSources.delete(key);
4441
- this.requireOutputs.delete(key);
4442
- this.waitForStacks.delete(key);
4443
- this.stackBases.delete(key);
4444
- this.stackSources.delete(key);
4445
- this.cycles.delete(key);
4446
- this.cycleModes.delete(key);
4447
- this.cycleDeltaBases.delete(key);
4448
- this.directCycleValues.delete(key);
4449
- this.directCycleFields.delete(key);
4450
- }
4451
- getConfig(worldId, entityId, loader, loaderFilter = null, filterSlots = null) {
4452
- const key = this.#key(worldId, entityId);
4453
- const pick = this.currentPicks.has(key) ? this.currentPicks.get(key) : this.#pick(key, loader);
4454
- const place = this.currentPlaces.has(key) ? this.currentPlaces.get(key) : this.#place(key, loader);
4455
- const stackBase = this.stackBases.get(key) ?? 16;
4456
- const stackSource = this.stackSources.get(key) ?? "q32";
4457
- const stackField = stackSource === "fixed" ? null : loader?.[stackSource];
4458
- const stack = stackField == null ? this.stackBases.has(key) || this.hasPositionConfig(worldId, entityId) ? stackBase : null : stackBase + stackField;
4459
- const cycle = this.cycles.has(key) ? this.cycles.get(key) : loader?.q40 == null || loader.q36 == null ? null : (loader.q40 + loader.q36) / 20 + 1;
4460
- return {
4461
- pick,
4462
- place,
4463
- priority: this.priorities.has(key) ? this.priorities.get(key) : DEFAULT_LOADER_PRIORITY,
4464
- requireOutput: this.requireOutputs.has(key) ? this.requireOutputs.get(key) : false,
4465
- waitForStack: this.waitForStacks.has(key) ? this.waitForStacks.get(key) : false,
4466
- stack: stack ?? DEFAULT_LOADER_STACK,
4467
- cycle: cycle ?? DEFAULT_LOADER_CYCLE,
4468
- filterMode: loaderFilter ? loaderFilter.q20 ?? DEFAULT_LOADER_FILTER_MODE : this.#filterMode(key, loader) ?? DEFAULT_LOADER_FILTER_MODE,
4469
- filterSlots: filterSlots ? [filterSlotValue(filterSlots.q20), filterSlotValue(filterSlots.q24), filterSlotValue(filterSlots.q28)] : null
4470
- };
4471
- }
4472
- hasPositionConfig(worldId, entityId) {
4473
- const key = this.#key(worldId, entityId);
4474
- return this.pickBases.has(key) && this.placeBases.has(key);
4475
- }
4476
- #hasTrackedConfig(key) {
4477
- return this.pickBases.has(key) || this.placeBases.has(key) || this.priorities.has(key) || this.priorityOffsets.has(key) || this.filterModes.has(key) || this.requireOutputs.has(key) || this.waitForStacks.has(key) || this.stackBases.has(key) || this.cycles.has(key);
4478
- }
4479
- #fieldChanged(previous, loader, field) {
4480
- return previous != null && loader != null && previous[field] !== loader[field];
4481
- }
4482
- #usesQ44CycleBase(key) {
4483
- const mode = this.cycleModes.get(key);
4484
- return mode === "q44-q36-delta";
4485
- }
4486
- #initializePositionBaseline(key, loader, mask) {
4487
- const hasQ28PositionBase = loader.q28 != null && mask & 4;
4488
- if (loader.q24 != null) {
4489
- this.pickBases.set(key, wrapLoaderPosition(loader.q24 + 3));
4490
- this.pickDeltaBases.set(key, loader.q20 ?? 0);
4491
- this.placeDeltaBases.set(key, loader.q24);
4492
- const initialPlace = hasQ28PositionBase ? loader.q28 + 4 : loader.q36 == null ? null : loader.q36 + 4;
4493
- if (initialPlace != null) this.placeBases.set(key, wrapLoaderPosition(initialPlace));
4494
- return hasQ28PositionBase;
4495
- }
4496
- if (hasQ28PositionBase) {
4497
- this.pickBases.set(key, wrapLoaderPosition(loader.q28 + 3));
4498
- this.pickDeltaBases.set(key, 0);
4499
- this.placeBases.set(key, 4);
4500
- this.placeDeltaBases.set(key, 0);
4501
- return true;
4502
- }
4503
- if (loader.q20 != null && loader.q36 != null) {
4504
- this.pickBases.set(key, wrapLoaderPosition(loader.q36 + 3));
4505
- this.pickDeltaBases.set(key, 0);
4506
- this.placeBases.set(key, 4);
4507
- this.placeDeltaBases.set(key, 0);
4508
- }
4509
- return false;
4510
- }
4511
- #initializeCycleBaseline(key, loader) {
4512
- if (loader?.q44 != null && (loader.q36 == null || loader.q40 == null)) {
4513
- this.cycleModes.set(key, "q44-q36-delta");
4514
- this.cycleDeltaBases.set(key, loader.q36 ?? 0);
4515
- this.directCycleValues.set(key, loader.q44);
4516
- this.directCycleFields.set(key, "q44");
4517
- this.cycles.set(key, loader.q44 / 20 + 1);
4518
- return;
4519
- }
4520
- if (loader?.q40 == null || loader.q36 == null) return;
4521
- this.cycleModes.set(key, "offset");
4522
- this.cycleDeltaBases.set(key, loader.q36 ?? 0);
4523
- this.directCycleValues.delete(key);
4524
- this.directCycleFields.delete(key);
4525
- this.cycles.set(key, loader.q40 / 20 + 1);
4526
- }
4527
- #initializeStackBaseline(key, loader) {
4528
- if (this.stackBases.has(key)) return;
4529
- if (loader?.q32 == null) return;
4530
- const baseline = this.#loaderBaseline(loader, loader?.lastMask);
4531
- if (baseline) {
4532
- this.stackBases.set(key, baseline.stack - loader.q32);
4533
- return;
4534
- }
4535
- if (loader.q20 == null && loader.q24 == null && loader.q28 == null && loader.q36 != null) {
4536
- this.stackBases.set(key, 17 + loader.q36);
4537
- return;
4538
- }
4539
- this.stackBases.set(key, 16);
4540
- }
4541
- #initializePriorityOffset(key, loader) {
4542
- if (loader?.q28 == null || loader?.q36 == null) return;
4543
- const offset = loader.q36 + 2;
4544
- const priority = loader.q28 + offset;
4545
- if (priority < -1 || priority > 1) return;
4546
- this.priorityOffsets.set(key, offset);
4547
- this.priorities.set(key, priority);
4548
- }
4549
- #priority(key, q28) {
4550
- return q28 + (this.priorityOffsets.get(key) ?? 0);
4551
- }
4552
- #updateCycle(key, loader) {
4553
- const mode = this.cycleModes.get(key);
4554
- if (mode === "direct") {
4555
- if (loader?.q36 != null) {
4556
- this.directCycleValues.set(key, loader.q36);
4557
- this.directCycleFields.set(key, "q36");
4558
- this.cycles.set(key, loader.q36 / 20 + 1);
4559
- } else if (loader?.q44 != null) {
4560
- this.directCycleValues.set(key, loader.q44);
4561
- this.directCycleFields.set(key, "q44");
4562
- this.cycles.set(key, loader.q44 / 20 + 1);
4563
- }
4564
- return;
4565
- }
4566
- if (mode === "q44-q36-delta") {
4567
- const base = loader?.q44 ?? this.directCycleValues.get(key);
4568
- if (base != null) {
4569
- this.directCycleValues.set(key, base);
4570
- this.directCycleFields.set(key, "q44");
4571
- const q36 = loader?.q36 ?? 0;
4572
- this.cycles.set(key, base < 0 && loader?.q36 != null ? q36 / 20 + 1 : (base + q36 - (this.cycleDeltaBases.get(key) ?? 0)) / 20 + 1);
4573
- }
4574
- return;
4575
- }
4576
- if (mode === "q40-direct") {
4577
- if (loader?.q40 != null) {
4578
- this.directCycleValues.set(key, loader.q40);
4579
- this.directCycleFields.set(key, "q40");
4580
- this.cycles.set(key, loader.q40 / 20 + 1);
4581
- }
4582
- return;
4583
- }
4584
- if (loader?.q40 == null) {
4585
- if (loader?.q44 != null || loader?.q36 != null) this.cycles.set(key, (loader.q44 ?? loader.q36) / 20 + 1);
4586
- return;
4587
- }
4588
- const deltaBase = this.cycleDeltaBases.get(key) ?? 0;
4589
- this.cycles.set(key, (loader.q40 + (loader.q36 ?? 0) - deltaBase) / 20 + 1);
4590
- }
4591
- #isDirectPositionCycleBaseline(loader, mask) {
4592
- return (mask & 19) === 19 && loader.q20 != null && loader.q24 != null && loader.q36 != null && loader.q40 == null && loader.q44 == null;
4593
- }
4594
- #trackedConfig(worldId, entityId) {
4595
- const key = this.#key(worldId, entityId);
4596
- if (!this.#hasTrackedConfig(key)) return null;
4597
- return {
4598
- pick: this.currentPicks.has(key) ? this.currentPicks.get(key) : this.pickBases.get(key),
4599
- place: this.currentPlaces.has(key) ? this.currentPlaces.get(key) : this.placeBases.get(key),
4600
- priority: this.priorities.get(key) ?? DEFAULT_LOADER_PRIORITY,
4601
- requireOutput: this.requireOutputs.get(key) ?? false,
4602
- waitForStack: this.waitForStacks.get(key) ?? false,
4603
- stack: this.stackBases.get(key) ?? DEFAULT_LOADER_STACK,
4604
- cycle: this.cycles.get(key) ?? DEFAULT_LOADER_CYCLE
4605
- };
4606
- }
4607
- #isSparsePositionBaseline(loader, mask) {
4608
- return (mask & 3) === 3 && loader.q20 != null && loader.q24 != null && loader.q28 == null && loader.q32 == null && loader.q36 == null && loader.q44 == null;
4609
- }
4610
- #applySparsePositionBaseline(key, loader, mask) {
4611
- const pickField = loader.q40 == null ? loader.q20 : loader.q24;
4612
- const placeField = loader.q40 == null ? loader.q24 : loader.q40;
4613
- const pick = wrapLoaderPosition(pickField + 3);
4614
- const place = wrapLoaderPosition(placeField + 4);
4615
- this.pickBases.set(key, pick);
4616
- this.pickDeltaBases.set(key, loader.q20 ?? 0);
4617
- this.placeBases.set(key, place);
4618
- this.placeDeltaBases.set(key, loader.q24 ?? 0);
4619
- this.currentPicks.set(key, pick);
4620
- this.currentPlaces.set(key, place);
4621
- this.sparsePositionBaselines.add(key);
4622
- this.priorities.set(key, DEFAULT_LOADER_PRIORITY);
4623
- this.requireOutputs.set(key, Boolean(mask & 32));
4624
- this.waitForStacks.set(key, Boolean(mask & 64));
4625
- this.stackBases.set(key, DEFAULT_LOADER_STACK);
4626
- this.cycles.set(key, DEFAULT_LOADER_CYCLE);
4627
- }
4628
- #filterMode(key, loader) {
4629
- if (this.filterSources.get(key) === "q32" && loader?.q32 != null) {
4630
- return this.#validFilterMode(loader.q32);
4631
- }
4632
- if (this.filterModes.has(key)) return this.#validFilterMode(this.filterModes.get(key));
4633
- const baseline = this.#loaderBaseline(loader, loader?.lastMask);
4634
- if (!baseline) return null;
4635
- return this.#validFilterMode(baseline.filterMode);
4636
- }
4637
- #validFilterMode(mode) {
4638
- return mode >= 0 && mode <= 3 ? mode : null;
4639
- }
4640
- #semanticFilterMode(loader, mask) {
4641
- const q28IsDirectPriority = loader.q28 != null && loader.q28 >= -1 && loader.q28 <= 1;
4642
- const q24FilterMode = loader.q24 != null && loader.q32 != null && loader.q40 != null ? loader.q24 + 2 : null;
4643
- const q28FilterMode = loader.q28 != null && loader.q32 != null ? loader.q28 + 1 : null;
4644
- const q32FilterMode = !q28IsDirectPriority && loader.q28 != null && loader.q32 != null && loader.q40 != null ? loader.q32 + 1 : null;
4645
- const q32DirectMode = loader.q28 == null && loader.q32 != null && mask & 32 ? loader.q32 : null;
4646
- if (q28IsDirectPriority && this.#validFilterMode(q24FilterMode) != null) return q24FilterMode;
4647
- if (this.#validFilterMode(q28FilterMode) != null) return q28FilterMode;
4648
- if (this.#validFilterMode(q32FilterMode) != null) return q32FilterMode;
4649
- if (this.#validFilterMode(q32DirectMode) != null) return q32DirectMode;
4650
- if (this.#validFilterMode(q24FilterMode) != null) return q24FilterMode;
4651
- return null;
4652
- }
4653
- #semanticFilterField(loader, mask) {
4654
- const q32DirectMode = loader.q28 == null && loader.q32 != null && mask & 32 ? loader.q32 : null;
4655
- return this.#validFilterMode(q32DirectMode) != null ? "q32" : null;
4656
- }
4657
- #loaderBaseline(loader, mask = loader?.lastMask, semanticSnapshot = false) {
4658
- const snapshot = semanticSnapshot ? decodeLoaderSnapshotRecord(loader, mask) : null;
4659
- if (snapshot) {
4660
- return {
4661
- pickBase: snapshot.pick,
4662
- pickDeltaBase: loader.q20 ?? 0,
4663
- placeBase: snapshot.place,
4664
- placeDeltaBase: loader.q24 ?? 0,
4665
- priority: snapshot.priority,
4666
- stack: snapshot.stack,
4667
- stackField: "fixed",
4668
- cycle: snapshot.cycle,
4669
- cycleMode: loader.q44 != null && loader.q40 == null ? "q44-q36-delta" : "offset",
4670
- filterMode: this.#semanticFilterMode(loader, mask),
4671
- filterField: this.#semanticFilterField(loader, mask),
4672
- q32: loader.q32 ?? 0
4673
- };
4674
- }
4675
- if (!loader || loader.q36 == null) return null;
4676
- if (loader.q40 == null && loader.q44 == null) {
4677
- if (loader.q20 != null || loader.q24 == null || loader.q28 == null || loader.q32 == null) return null;
4678
- return {
4679
- pickBase: wrapLoaderPosition(loader.q28 + 2),
4680
- pickDeltaBase: 0,
4681
- placeBase: wrapLoaderPosition(loader.q24 + 4),
4682
- placeDeltaBase: loader.q24,
4683
- priority: loader.q28,
4684
- stack: 16 + loader.q32,
4685
- cycle: loader.q36 / 20 + 1,
4686
- cycleMode: "direct",
4687
- filterMode: loader.q28 + 1,
4688
- q32: loader.q32
4689
- };
4690
- }
4691
- if (loader.q24 == null && loader.q28 == null && loader.q20 != null && loader.q32 != null && loader.q40 != null && loader.q44 != null) {
4692
- return {
4693
- pickBase: wrapLoaderPosition(loader.q20 + 7),
4694
- pickDeltaBase: loader.q20,
4695
- placeBase: 4,
4696
- placeDeltaBase: 0,
4697
- priority: 0,
4698
- stack: 16 + loader.q36,
4699
- stackField: "q36",
4700
- cycle: loader.q40 / 20 + 1,
4701
- cycleMode: "q40-direct",
4702
- filterMode: loader.q32,
4703
- filterField: "q32",
4704
- q32: loader.q32
4705
- };
4706
- }
4707
- const q20 = loader.q20 ?? 0;
4708
- const q32 = loader.q32 ?? 0;
4709
- let pickBase = null;
4710
- let placeBase = null;
4711
- if (loader.q44 != null && loader.q40 == null && loader.q28 == null && loader.q24 != null && loader.q32 != null) {
4712
- pickBase = wrapLoaderPosition(loader.q24 + 3);
4713
- placeBase = wrapLoaderPosition(loader.q32 + 4);
4714
- } else if (loader.q24 != null) {
4715
- pickBase = wrapLoaderPosition(loader.q24 + 3);
4716
- placeBase = loader.q28 != null ? wrapLoaderPosition(loader.q28 + 4) : wrapLoaderPosition(loader.q36 + 4);
4717
- } else if (loader.q28 != null) {
4718
- pickBase = wrapLoaderPosition(loader.q28 + 3);
4719
- placeBase = 4;
4720
- } else if (loader.q20 != null) {
4721
- pickBase = wrapLoaderPosition(loader.q36 + 3);
4722
- placeBase = 4;
4723
- }
4724
- if (pickBase == null || placeBase == null) return null;
4725
- const q28IsDirectPriority = loader.q28 != null && loader.q28 >= -1 && loader.q28 <= 1;
4726
- const priority = loader.q28 != null && loader.q32 != null && loader.q44 != null && loader.q40 != null ? loader.q32 : loader.q28 != null && loader.q32 != null && loader.q44 == null && loader.q40 == null ? loader.q28 : loader.q28 != null && loader.q32 != null && loader.q44 == null && loader.q40 != null ? loader.q32 : loader.q32 != null && loader.q44 != null && loader.q40 == null ? loader.q32 : null;
4727
- const q28FilterMode = loader.q28 != null && loader.q32 != null && loader.q44 != null ? loader.q28 + 1 : null;
4728
- const q24FilterMode = loader.q24 != null && loader.q32 != null && loader.q44 != null && loader.q40 != null ? loader.q24 + 2 : null;
4729
- const q32FilterMode = !q28IsDirectPriority && loader.q28 != null && loader.q32 != null && loader.q44 != null && loader.q40 != null ? loader.q32 + 1 : null;
4730
- const filterMode = q28IsDirectPriority && q24FilterMode != null && q24FilterMode >= 0 && q24FilterMode <= 3 ? q24FilterMode : q28FilterMode != null && q28FilterMode >= 0 && q28FilterMode <= 3 ? q28FilterMode : q32FilterMode != null && q32FilterMode >= 0 && q32FilterMode <= 3 ? q32FilterMode : q24FilterMode;
4731
- return {
4732
- pickBase,
4733
- pickDeltaBase: q20,
4734
- placeBase,
4735
- placeDeltaBase: loader.q24 ?? 0,
4736
- priority,
4737
- stack: loader.q32 == null ? null : 16 + loader.q36,
4738
- cycle: (loader.q40 ?? loader.q44) / 20 + 1,
4739
- cycleMode: loader.q44 != null && loader.q40 == null ? "q44-q36-delta" : "offset",
4740
- filterMode,
4741
- q32
4742
- };
4743
- }
4744
- #applyLoaderBaseline(key, loader, baseline) {
4745
- this.pickBases.set(key, baseline.pickBase);
4746
- this.pickDeltaBases.set(key, baseline.pickDeltaBase);
4747
- this.placeBases.set(key, baseline.placeBase);
4748
- this.placeDeltaBases.set(key, baseline.placeDeltaBase);
4749
- this.sparsePositionBaselines.delete(key);
4750
- this.#setCurrentPosition(key, loader);
4751
- if (baseline.filterMode != null) {
4752
- this.filterModes.set(key, baseline.filterMode);
4753
- if (baseline.filterField) this.filterSources.set(key, baseline.filterField);
4754
- else this.filterSources.delete(key);
4755
- }
4756
- if (baseline.stack != null) {
4757
- const stackField = baseline.stackField === "fixed" ? 0 : baseline.stackField ? loader[baseline.stackField] ?? 0 : baseline.q32;
4758
- this.stackBases.set(key, baseline.stack - stackField);
4759
- if (baseline.stackField) this.stackSources.set(key, baseline.stackField);
4760
- else this.stackSources.delete(key);
4761
- }
4762
- this.cycleModes.set(key, baseline.cycleMode);
4763
- if (baseline.cycleMode === "direct") {
4764
- this.cycleDeltaBases.set(key, 0);
4765
- this.directCycleValues.set(key, loader.q44 ?? loader.q36);
4766
- this.directCycleFields.set(key, loader.q44 == null ? "q36" : "q44");
4767
- } else if (baseline.cycleMode === "q44-q36-delta") {
4768
- this.cycleDeltaBases.set(key, loader.q36 ?? 0);
4769
- this.directCycleValues.set(key, loader.q44);
4770
- this.directCycleFields.set(key, "q44");
4771
- } else if (baseline.cycleMode === "q40-direct") {
4772
- this.cycleDeltaBases.set(key, 0);
4773
- this.directCycleValues.set(key, loader.q40);
4774
- this.directCycleFields.set(key, "q40");
4775
- } else {
4776
- this.cycleDeltaBases.set(key, loader.q36 ?? 0);
4777
- this.directCycleValues.delete(key);
4778
- this.directCycleFields.delete(key);
4779
- }
4780
- this.cycles.set(key, baseline.cycle);
4781
- if (baseline.priority != null && baseline.priority >= -1 && baseline.priority <= 1) {
4782
- if (loader.q28 != null) this.priorityOffsets.set(key, baseline.priority - loader.q28);
4783
- this.priorities.set(key, baseline.priority);
4784
- } else if (loader.q28 != null && loader.q36 != null) this.#initializePriorityOffset(key, loader);
4785
- }
4786
- #applySemanticDelta(worldId, entityId, loader, mask, previous, deltaRecord) {
4787
- const key = this.#key(worldId, entityId);
4788
- const delta = decodeLoaderSemanticDeltaRecord(deltaRecord ?? loaderDeltaRecord(loader, mask, previous), mask);
4789
- if (!delta) return false;
4790
- const previousConfig = this.getConfig(worldId, entityId, previous);
4791
- const pick = delta.pick == null ? previousConfig.pick : wrapLoaderPosition((previousConfig.pick ?? DEFAULT_LOADER_PICK) + delta.pick);
4792
- const place = delta.place == null ? previousConfig.place : wrapLoaderPosition((previousConfig.place ?? DEFAULT_LOADER_PLACE) + delta.place);
4793
- if (pick != null) {
4794
- this.pickBases.set(key, pick);
4795
- this.pickDeltaBases.set(key, loader?.q20 ?? 0);
4796
- this.currentPicks.set(key, pick);
4797
- }
4798
- if (place != null) {
4799
- this.placeBases.set(key, place);
4800
- this.placeDeltaBases.set(key, loader?.q24 ?? 0);
4801
- this.currentPlaces.set(key, place);
4802
- }
4803
- if (delta.priority != null) {
4804
- const priority = previousConfig.priority + delta.priority;
4805
- this.priorities.set(key, priority);
4806
- if (loader?.q28 != null) this.priorityOffsets.set(key, priority - loader.q28);
4807
- else this.priorityOffsets.delete(key);
4808
- }
4809
- if (delta.stack != null) {
4810
- this.stackBases.set(key, previousConfig.stack + delta.stack);
4811
- this.stackSources.set(key, "fixed");
4812
- }
4813
- if (delta.cycleTicks != null) {
4814
- this.cycles.set(key, previousConfig.cycle + delta.cycleTicks / 20);
4815
- if (loader?.q44 != null && loader.q40 == null) {
4816
- this.cycleModes.set(key, "q44-q36-delta");
4817
- this.cycleDeltaBases.set(key, loader.q36 ?? 0);
4818
- this.directCycleValues.set(key, loader.q44);
4819
- this.directCycleFields.set(key, "q44");
4820
- } else {
4821
- this.cycleModes.set(key, "offset");
4822
- this.cycleDeltaBases.set(key, loader?.q36 ?? 0);
4823
- this.directCycleValues.delete(key);
4824
- this.directCycleFields.delete(key);
4825
- }
4826
- }
4827
- if (delta.requireOutput) this.requireOutputs.set(key, !previousConfig.requireOutput);
4828
- if (delta.waitForStack) this.waitForStacks.set(key, !previousConfig.waitForStack);
4829
- this.sparsePositionBaselines.delete(key);
4830
- return true;
4831
- }
4832
- #setCurrentPosition(key, loader) {
4833
- const pick = this.#pick(key, loader);
4834
- const place = this.#place(key, loader);
4835
- if (pick != null) this.currentPicks.set(key, pick);
4836
- if (place != null) this.currentPlaces.set(key, place);
4837
- }
4838
- #pick(key, loader) {
4839
- if (!loader) return null;
4840
- if (this.pickBases.has(key)) return wrapLoaderPosition(this.pickBases.get(key) + ((loader.q20 ?? 0) - (this.pickDeltaBases.get(key) ?? 0)));
4841
- if (loader.q24 != null) return wrapLoaderPosition(loader.q24 + 3);
4842
- if (loader.q36 != null) return wrapLoaderPosition(loader.q36 + 3);
4843
- if (loader.q20 != null) return wrapLoaderPosition(loader.q20);
4844
- return null;
4845
- }
4846
- #place(key, loader) {
4847
- if (!loader) return null;
4848
- if (this.placeBases.has(key)) {
4849
- const base = this.placeBases.get(key);
4850
- if (loader.q24 != null && this.placeDeltaBases.has(key)) {
4851
- return wrapLoaderPosition(base + (loader.q24 - this.placeDeltaBases.get(key)));
4852
- }
4853
- return wrapLoaderPosition(base);
4854
- }
4855
- if (loader.q36 != null) return loader.q24 == null ? 4 : wrapLoaderPosition(loader.q36 + 4);
4856
- return null;
4857
- }
4858
- #key(worldId, entityId) {
4859
- return `${worldId ?? "-"}:${entityId}`;
4860
- }
4861
- };
4862
4007
 
4863
4008
  // src/state/overworld.js
4864
4009
  var OVERWORLD_ZONES = Object.freeze([
@@ -5545,7 +4690,11 @@
5545
4690
  [63, { name: "numeric_pair", ...TWO_FIELD_SPEC }],
5546
4691
  [67, { name: "numeric_single", fields: numericFields({ 1: 20 }) }],
5547
4692
  [69, {
5548
- name: "rare_snapshot",
4693
+ name: "loader_config",
4694
+ // The official loader component starts with these values. Wire section
4695
+ // 162 sends a packed absolute flag word before the five numeric deltas.
4696
+ defaults: { q20: 3, q24: 4, q28: 1, q32: 16, q36: 20, q41: 0, q42: 0 },
4697
+ packedBeforeValues: true,
5549
4698
  packedBits: [{ bit: 32, offset: 41 }, { bit: 64, offset: 42 }],
5550
4699
  fields: numericFields({ 1: 20, 2: 24, 4: 28, 8: 32, 16: 36 })
5551
4700
  }],
@@ -5661,7 +4810,8 @@
5661
4810
  [158, 75],
5662
4811
  [160, 76],
5663
4812
  [161, 77],
5664
- [162, 78],
4813
+ [162, 69],
4814
+ // Loader configuration; distinct from navigation state (168).
5665
4815
  [163, 72],
5666
4816
  [164, 73],
5667
4817
  [165, 74],
@@ -5835,27 +4985,6 @@
5835
4985
  }
5836
4986
  return null;
5837
4987
  }
5838
- var TABLE_78_FIELD_BITS = [
5839
- ["q20", 1],
5840
- ["q24", 2],
5841
- ["q28", 4],
5842
- ["q32", 8],
5843
- ["q36", 16],
5844
- ["q40", 32],
5845
- ["q44", 64]
5846
- ];
5847
- function table78DeltaRecord(changed) {
5848
- const record = { lastMask: changed.mask };
5849
- for (const [field, bit] of TABLE_78_FIELD_BITS) {
5850
- if (!(changed.mask & bit)) continue;
5851
- if (field === "q44" && (changed.mask & 32 || changed.record?.q44 == null)) continue;
5852
- record[field] = (changed.record?.[field] ?? 0) - (changed.previous?.[field] ?? 0);
5853
- }
5854
- return record;
5855
- }
5856
- function isSemanticLoaderDelta2(changed, full) {
5857
- return !full && changed.previous != null && (changed.mask & 96) === 96;
5858
- }
5859
4988
  function decodeText(blob) {
5860
4989
  if (!(blob instanceof Uint8Array)) return null;
5861
4990
  try {
@@ -5927,8 +5056,12 @@
5927
5056
  active: record?.q33 == null ? null : Boolean(record.q33)
5928
5057
  };
5929
5058
  }
5930
- function summarizeCannon(entity, record, typeId = null) {
5059
+ function summarizeCannon(entity, record, typeId = null, transformRecord = null) {
5931
5060
  if (!record || !CANNON_TYPE_IDS.has(typeId)) return null;
5061
+ const relativeAngleRadians = numberOrNull(record.q32, 200);
5062
+ const mountingAngleRadians = numberOrNull(transformRecord?.q28, 127.324);
5063
+ const tau = 2 * Math.PI;
5064
+ const absoluteAngleRadians = relativeAngleRadians == null || mountingAngleRadians == null ? null : ((mountingAngleRadians + relativeAngleRadians) % tau + tau) % tau;
5932
5065
  const ammoItemId = record.q24 == null ? null : CANNON_AMMO_COLOR_ITEM_IDS.get(record.q24) ?? null;
5933
5066
  const charge = record.q40 ?? null;
5934
5067
  const recoil = record.q36 ?? null;
@@ -5940,7 +5073,8 @@
5940
5073
  ammoItemId,
5941
5074
  ammoName: entityNameFromType(ammoItemId),
5942
5075
  ammoCount: record.q28 ?? 0,
5943
- aim: record.q32 ?? null,
5076
+ relativeAngleRadians,
5077
+ absoluteAngleRadians,
5944
5078
  recoil,
5945
5079
  recoil2,
5946
5080
  recoils: [recoil, recoil2],
@@ -6316,15 +5450,13 @@
6316
5450
  state: cloneRecord(markerRecord)
6317
5451
  };
6318
5452
  }
6319
- function summarizeLoader(entity, loaderRecord, loaderFilterRecord = null, filterSlotsRecord = null, tracker = null, includeDefaults = false, itemHolderRecord = null) {
5453
+ function summarizeLoader(entity, loaderRecord, loaderFilterRecord = null, filterSlotsRecord = null, includeDefaults = false, itemHolderRecord = null) {
6320
5454
  if (!loaderRecord && !loaderFilterRecord && !includeDefaults) return null;
6321
- const config = tracker?.getConfig(null, entity, loaderRecord, loaderFilterRecord, filterSlotsRecord) ?? {};
6322
- const hasLoaderState = Boolean(loaderRecord);
6323
- const hasPositionConfig = Boolean(tracker?.hasPositionConfig(null, entity));
6324
- const pick = hasLoaderState && hasPositionConfig ? config.pick ?? null : null;
6325
- const place = hasLoaderState && hasPositionConfig ? config.place ?? null : null;
6326
- const priority = config.priority ?? 0;
6327
- const filterMode = config.filterMode ?? null;
5455
+ const loader = { ...MODEL_TABLE_SPECS.get(69).defaults, ...loaderRecord };
5456
+ const pick = loader.q20;
5457
+ const place = loader.q24;
5458
+ const priority = loader.q28 - 1;
5459
+ const filterMode = loaderFilterRecord?.q20 ?? 0;
6328
5460
  const heldItem = itemSummary(itemHolderRecord?.q20, itemHolderRecord?.q24 ?? null);
6329
5461
  return {
6330
5462
  entity,
@@ -6334,13 +5466,13 @@
6334
5466
  placeName: enumValueName(LOADER_POSITION_NAMES, place),
6335
5467
  priority,
6336
5468
  priorityName: enumValueName(LOADER_PRIORITY_NAMES, priority),
6337
- requireOutput: config.requireOutput ?? false,
6338
- waitForStack: config.waitForStack ?? false,
6339
- stack: config.stack ?? 16,
6340
- cycle: Math.max(1, config.cycle ?? 1),
5469
+ requireOutput: Boolean(loader.q41),
5470
+ waitForStack: Boolean(loader.q42),
5471
+ stack: loader.q32,
5472
+ cycle: loader.q36 / 20,
6341
5473
  filterMode,
6342
5474
  filterModeName: enumValueName(LOADER_FILTER_MODE_NAMES, filterMode),
6343
- filterSlots: config.filterSlots ?? null,
5475
+ filterSlots: filterSlotsRecord ? [filterSlotsRecord.q20, filterSlotsRecord.q24, filterSlotsRecord.q28].map((value) => value || null) : null,
6344
5476
  heldItemId: heldItem.itemId,
6345
5477
  heldItemName: heldItem.itemName,
6346
5478
  heldCount: heldItem.count,
@@ -6378,7 +5510,7 @@
6378
5510
  filteredModeName: enumValueName(PUSHER_MODE_NAMES, filteredMode),
6379
5511
  angle: numberOrNull(pusherRecord.q28, 10),
6380
5512
  speed: pusherRecord.q32 == null ? 20 : pusherRecord.q32 / 100 + 20,
6381
- length: pusherRecord.q40 == null ? 1e3 : (pusherRecord.q40 + 50) / 10 + 995,
5513
+ length: 1e3 + (pusherRecord.q40 ?? 0) / 10,
6382
5514
  filterInventory: pusherRecord.q36 === 1,
6383
5515
  filterSlots: filterSlotsRecord ? [filterSlotsRecord.q20 ?? null, filterSlotsRecord.q24 ?? null, filterSlotsRecord.q28 ?? null] : null,
6384
5516
  state: cloneRecord(pusherRecord),
@@ -6731,9 +5863,6 @@
6731
5863
  blobKey: blobKey2,
6732
5864
  cloneRecord: cloneRecord2,
6733
5865
  firstRecord: firstRecord2,
6734
- TABLE_78_FIELD_BITS: TABLE_78_FIELD_BITS2,
6735
- table78DeltaRecord: table78DeltaRecord2,
6736
- isSemanticLoaderDelta: isSemanticLoaderDelta3,
6737
5866
  decodeText: decodeText2,
6738
5867
  entityNameFromType: entityNameFromType2,
6739
5868
  markerTypeIdForTables: markerTypeIdForTables2,
@@ -6809,7 +5938,6 @@
6809
5938
  defineLazyProperty: defineLazyProperty2
6810
5939
  } = decoder_exports;
6811
5940
  var ModelState = class {
6812
- #loaderConfig = new LoaderConfigTracker();
6813
5941
  #blueprintItems = null;
6814
5942
  #helmOccupied = /* @__PURE__ */ new Map();
6815
5943
  #commsStationOccupied = /* @__PURE__ */ new Map();
@@ -6898,8 +6026,6 @@
6898
6026
  this.totalErrorCount += 1;
6899
6027
  pushCapped2(this.errors, { message: error.message, generation: update.generation }, MAX_RETAINED_ERRORS2);
6900
6028
  }
6901
- this.#remapIndexedLoaderConfig(update);
6902
- this.#updateLoaderConfig(update);
6903
6029
  this.#updateNavigationUnitAutoWarp(update);
6904
6030
  this.#updateHelmOccupancy(update);
6905
6031
  this.#updateCommsStationOccupancy(update);
@@ -7001,53 +6127,6 @@
7001
6127
  this._derived.summariesDirty = true;
7002
6128
  this._derived.tableSummariesDirty = true;
7003
6129
  }
7004
- #updateLoaderConfig(update) {
7005
- const seenEntities = /* @__PURE__ */ new Set();
7006
- for (const section of update.sections || []) {
7007
- if (section.table !== 78) continue;
7008
- for (const changed of section.records || []) {
7009
- if (changed.indexedLoaderConfig) {
7010
- this.#loaderConfig.updateIndexedSnapshotRecord(null, changed.entity, changed.record, changed.mask, changed.cumulativeRecord, changed.configEntity);
7011
- continue;
7012
- }
7013
- const typeId = entityTypeIdFromRecord2(this.record(7, changed.entity));
7014
- this.#loaderConfig.updateRecord(null, changed.entity, changed.record ?? this.record(78, changed.entity), changed.mask, changed.previous, {
7015
- repeatedInUpdate: seenEntities.has(changed.entity),
7016
- allowSparseBaseline: typeId === LOADER_TYPE_ID2,
7017
- repeatedInSection: changed.repeatedInSection,
7018
- semanticSnapshot: Boolean(update.full),
7019
- semanticDelta: isSemanticLoaderDelta3(changed, update.full),
7020
- deltaRecord: table78DeltaRecord2(changed)
7021
- });
7022
- seenEntities.add(changed.entity);
7023
- }
7024
- }
7025
- }
7026
- #remapIndexedLoaderConfig(update) {
7027
- if (!update.full || update.error) return;
7028
- const rows = [];
7029
- for (const section of update.sections || []) {
7030
- if (section.table !== 78) continue;
7031
- for (const changed of section.records || []) rows.push(changed);
7032
- }
7033
- if (!rows.length) return;
7034
- const loaderIds = [...this.table(7).entries()].filter(([, record]) => entityTypeIdFromRecord2(record) === LOADER_TYPE_ID2).map(([entity]) => entity).sort((a, b) => a - b);
7035
- if (loaderIds.length !== rows.length) return;
7036
- if (rows.every((row, index) => row.entity === loaderIds[index])) return;
7037
- const remappedTable = /* @__PURE__ */ new Map();
7038
- for (const [index, changed] of rows.entries()) {
7039
- const rawRecord = table78DeltaRecord2(changed);
7040
- changed.configEntity = changed.entity;
7041
- changed.entity = loaderIds[index];
7042
- changed.cumulativeRecord = cloneRecord2(changed.record || {});
7043
- changed.record = cloneRecord2(rawRecord);
7044
- delete changed.previous;
7045
- changed.indexedLoaderConfig = true;
7046
- remappedTable.set(changed.entity, cloneRecord2(rawRecord));
7047
- update.changedEntities.add(changed.entity);
7048
- }
7049
- this.tables.set(78, remappedTable);
7050
- }
7051
6130
  #updateNavigationUnitAutoWarp(update) {
7052
6131
  const trackedBeforeUpdate = new Set(this.#navigationUnitAutoWarp.keys());
7053
6132
  const initializedThisUpdate = /* @__PURE__ */ new Set();
@@ -7414,7 +6493,8 @@
7414
6493
  const pusherRecord = rec(72);
7415
6494
  const pusherBeamRecord = rec(42);
7416
6495
  const launcherRecord = rec(44);
7417
- const loaderRecord = rec(78);
6496
+ const loaderRecord = rec(69);
6497
+ const navigationRecord = rec(78);
7418
6498
  const loaderFilterRecord = rec(76);
7419
6499
  const loaderFilterSlotsRecord = rec(77);
7420
6500
  const commsStationRecord = rec(39);
@@ -7449,14 +6529,14 @@
7449
6529
  const health = summarizeHealth2(entityId, healthRecord);
7450
6530
  const fabricator = summarizeFabricator2(entityId, fabricatorRecord, itemHolderRecord, typeRecord);
7451
6531
  const cargoEjector = summarizeCargoEjector2(entityId, typeId, cargoEjectorRecord);
7452
- const cannon = summarizeCannon2(entityId, cannonRecord, typeId);
6532
+ const cannon = summarizeCannon2(entityId, cannonRecord, typeId, transformRecord);
7453
6533
  const thruster = summarizeThruster2(entityId, typeId, thrusterRecord);
7454
6534
  const pusher = summarizePusher2(entityId, pusherRecord, loaderFilterSlotsRecord);
7455
6535
  const pusherBeam = summarizePusherBeam2(entityId, pusherBeamRecord);
7456
6536
  const launcher = summarizeItemLauncher2(entityId, typeId, launcherRecord);
7457
- const loader = typeId === LOADER_TYPE_ID2 || typeId == null && (loaderRecord || loaderFilterRecord || loaderFilterSlotsRecord) ? summarizeLoader2(entityId, loaderRecord, loaderFilterRecord, loaderFilterSlotsRecord, this.#loaderConfig, typeId === LOADER_TYPE_ID2, itemHolderRecord) : null;
6537
+ const loader = typeId === LOADER_TYPE_ID2 || typeId == null && (loaderRecord || loaderFilterRecord || loaderFilterSlotsRecord) ? summarizeLoader2(entityId, loaderRecord, loaderFilterRecord, loaderFilterSlotsRecord, typeId === LOADER_TYPE_ID2, itemHolderRecord) : null;
7458
6538
  const cargoHatch = summarizeCargoHatch2(entityId, typeId, loaderFilterRecord, loaderFilterSlotsRecord, rec(45));
7459
- const navigationUnit = summarizeNavigationUnit2(entityId, typeId, loaderRecord, this.#navigationUnitAutoWarp.get(entityId));
6539
+ const navigationUnit = summarizeNavigationUnit2(entityId, typeId, navigationRecord, this.#navigationUnitAutoWarp.get(entityId));
7460
6540
  const fluidTank = fluidTankRecord ? {
7461
6541
  entity: entityId,
7462
6542
  amount: fluidTankRecord.q24 ?? null,
@@ -7703,7 +6783,6 @@
7703
6783
  } else {
7704
6784
  for (const records of this.tables.values()) records.delete(entity);
7705
6785
  }
7706
- this.#loaderConfig.delete(null, entity);
7707
6786
  this.#helmOccupied.delete(entity);
7708
6787
  this.#commsStationOccupied.delete(entity);
7709
6788
  this.#navigationUnitAutoWarp.delete(entity);
@@ -7719,7 +6798,6 @@
7719
6798
  #readSectionRecords(reader, tag, tableId, spec) {
7720
6799
  const section = { tag, table: tableId, name: spec?.name || null, records: [] };
7721
6800
  let entity = 0;
7722
- const seenEntities = tableId === 78 ? /* @__PURE__ */ new Set() : null;
7723
6801
  while (reader.remaining > 0) {
7724
6802
  const recordOffset = reader.offset;
7725
6803
  let delta;
@@ -7737,7 +6815,6 @@
7737
6815
  throw new Error(`model table ${tableId} tag ${tag} entity ${entity} mask offset ${reader.offset}: ${error.message}`);
7738
6816
  }
7739
6817
  const record = this.#getRecord(tableId, entity);
7740
- const previous = tableId === 78 ? cloneRecord2(record) : null;
7741
6818
  record.lastMask = mask;
7742
6819
  try {
7743
6820
  if (spec) this.#applyRecordSpec(reader, record, mask, spec);
@@ -7746,10 +6823,6 @@
7746
6823
  throw new Error(`model table ${tableId} tag ${tag} entity ${entity} mask ${mask} offset ${reader.offset}: ${error.message}`);
7747
6824
  }
7748
6825
  const changed = { entity, mask };
7749
- if (previous) changed.previous = previous;
7750
- if (seenEntities?.has(entity)) changed.repeatedInSection = true;
7751
- seenEntities?.add(entity);
7752
- if (tableId === 78) changed.record = cloneRecord2(record);
7753
6826
  section.records.push(changed);
7754
6827
  }
7755
6828
  return section;
@@ -7757,7 +6830,7 @@
7757
6830
  #getRecord(tableId, entity) {
7758
6831
  if (!this.tables.has(tableId)) this.tables.set(tableId, /* @__PURE__ */ new Map());
7759
6832
  const records = this.tables.get(tableId);
7760
- if (!records.has(entity)) records.set(entity, {});
6833
+ if (!records.has(entity)) records.set(entity, { ...MODEL_TABLE_SPECS2.get(tableId)?.defaults });
7761
6834
  return records.get(entity);
7762
6835
  }
7763
6836
  #applyRecordSpec(reader, record, mask, spec) {