@shipload/sdk 2.0.0-rc11 → 2.0.0-rc13

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/lib/shipload.m.js CHANGED
@@ -2132,6 +2132,11 @@ const SHIP_CARGO_NOT_LOADED = 'Cannot unload cargo that is not loaded.';
2132
2132
  const WAREHOUSE_NOT_FOUND = 'Cannot find warehouse for given id.';
2133
2133
  const WAREHOUSE_ALREADY_AT_LOCATION = 'Warehouse already exists at this location.';
2134
2134
  const WAREHOUSE_CAPACITY_EXCEEDED = 'Warehouse capacity would be exceeded.';
2135
+ const ENTITY_CAPACITY_EXCEEDED = 'Entity cargo capacity would be exceeded.';
2136
+ const RECIPE_INPUTS_INSUFFICIENT = 'Insufficient inputs for recipe.';
2137
+ const RECIPE_INPUTS_INVALID = 'Input cargo does not match recipe requirements.';
2138
+ const RECIPE_INPUTS_EXCESS = 'Provided inputs exceed recipe requirements.';
2139
+ const RECIPE_INPUTS_MIXED = 'All stacks for a recipe input must be the same resource.';
2135
2140
 
2136
2141
  const PRECISION$1 = 10000;
2137
2142
  const CRAFT_ENERGY_DIVISOR = 150000;
@@ -2155,7 +2160,8 @@ var TaskType;
2155
2160
  TaskType[TaskType["WARP"] = 6] = "WARP";
2156
2161
  TaskType[TaskType["CRAFT"] = 7] = "CRAFT";
2157
2162
  TaskType[TaskType["DEPLOY"] = 8] = "DEPLOY";
2158
- TaskType[TaskType["DEPLOY_SHIP"] = 9] = "DEPLOY_SHIP";
2163
+ TaskType[TaskType["WRAP"] = 9] = "WRAP";
2164
+ TaskType[TaskType["UNWRAP"] = 10] = "UNWRAP";
2159
2165
  })(TaskType || (TaskType = {}));
2160
2166
  var LocationType;
2161
2167
  (function (LocationType) {
@@ -2256,7 +2262,7 @@ const DEPTH_THRESHOLD_T4 = 30000;
2256
2262
  const DEPTH_THRESHOLD_T5 = 55000;
2257
2263
  const LOCATION_MIN_DEPTH = 500;
2258
2264
  const LOCATION_MAX_DEPTH = 65535;
2259
- const YIELD_THRESHOLD = Math.floor(0.003 * 0xffffffff);
2265
+ const YIELD_THRESHOLD = Math.floor(0.001 * 0xffffffff);
2260
2266
  const PLANET_SUBTYPE_GAS_GIANT = 0;
2261
2267
  const PLANET_SUBTYPE_ROCKY = 1;
2262
2268
  const PLANET_SUBTYPE_TERRESTRIAL = 2;
@@ -2374,12 +2380,6 @@ function getEligibleResources(locationType, subtype, stratum) {
2374
2380
  return stratum >= threshold;
2375
2381
  });
2376
2382
  }
2377
- function depthScaleFactor(stratum) {
2378
- if (stratum <= 1)
2379
- return 1.0;
2380
- const logScale = Math.log(stratum) / Math.log(65535);
2381
- return 1.0 + logScale * 2.0;
2382
- }
2383
2383
 
2384
2384
  function deriveLocationSize(loc) {
2385
2385
  if (loc.type.toNumber() === LocationType.EMPTY)
@@ -4568,10 +4568,14 @@ function isGatherableLocation(locationType) {
4568
4568
  }
4569
4569
  function getLocationTypeName(type) {
4570
4570
  switch (type) {
4571
- case LocationType.EMPTY: return 'Empty';
4572
- case LocationType.PLANET: return 'Planet';
4573
- case LocationType.ASTEROID: return 'Asteroid';
4574
- case LocationType.NEBULA: return 'Nebula';
4571
+ case LocationType.EMPTY:
4572
+ return 'Empty';
4573
+ case LocationType.PLANET:
4574
+ return 'Planet';
4575
+ case LocationType.ASTEROID:
4576
+ return 'Asteroid';
4577
+ case LocationType.NEBULA:
4578
+ return 'Nebula';
4575
4579
  }
4576
4580
  }
4577
4581
  function uint16(hash, offset) {
@@ -4901,1930 +4905,48 @@ var itemsData = [
4901
4905
  }
4902
4906
  ];
4903
4907
 
4904
- const items = itemsData.map((g) => Item.from({
4905
- id: g.id,
4906
- name: g.name,
4907
- description: g.description,
4908
- mass: g.mass,
4909
- category: g.category,
4910
- tier: g.tier,
4911
- color: g.color,
4912
- }));
4913
- const itemIds = items.map((i) => i.id);
4914
- function getItem(itemId) {
4915
- const id = UInt16.from(itemId);
4916
- const item = items.find((i) => i.id.equals(id));
4917
- if (!item) {
4918
- throw new Error(`Item with id ${id} not found`);
4919
- }
4920
- return item;
4921
- }
4922
- function getItems() {
4923
- return items;
4924
- }
4925
-
4926
- function calc_orbital_altitude(mass) {
4927
- if (mass <= BASE_ORBITAL_MASS) {
4928
- return MIN_ORBITAL_ALTITUDE;
4929
- }
4930
- const ratio = mass / BASE_ORBITAL_MASS;
4931
- const capRatio = 10.0;
4932
- let scale = Math.log(ratio) / Math.log(capRatio);
4933
- scale = Math.min(scale, 1.0);
4934
- return MIN_ORBITAL_ALTITUDE + Math.floor((MAX_ORBITAL_ALTITUDE - MIN_ORBITAL_ALTITUDE) * scale);
4935
- }
4936
- function distanceBetweenCoordinates(origin, destination) {
4937
- return distanceBetweenPoints(origin.x, origin.y, destination.x, destination.y);
4938
- }
4939
- function distanceBetweenPoints(x1, y1, x2, y2) {
4940
- const x = Math.pow(x1 - x2, 2);
4941
- const y = Math.pow(y1 - y2, 2);
4942
- return UInt64.from(Math.sqrt(x + y) * PRECISION$1);
4943
- }
4944
- function lerp(origin, destination, time) {
4945
- return {
4946
- x: (1 - time) * Number(origin.x) + time * Number(destination.x),
4947
- y: (1 - time) * Number(origin.y) + time * Number(destination.y),
4948
- };
4949
- }
4950
- function rotation(origin, destination) {
4951
- return Math.atan2(destination.y - origin.y, destination.x - origin.x) * (180 / Math.PI) + 90;
4952
- }
4953
- function findNearbyPlanets(seed, origin, maxDistance = 20 * PRECISION$1) {
4954
- const nearbySystems = [];
4955
- const max = UInt64.from(maxDistance / PRECISION$1);
4956
- const xMin = Int64.from(origin.x).subtracting(max);
4957
- const xMax = Int64.from(origin.x).adding(max);
4958
- const yMin = Int64.from(origin.y).subtracting(max);
4959
- const yMax = Int64.from(origin.y).adding(max);
4960
- for (let x = Number(xMin); x <= Number(xMax); x++) {
4961
- for (let y = Number(yMin); y <= Number(yMax); y++) {
4962
- const samePlace = x === Number(origin.x) && y === Number(origin.y);
4963
- if (!samePlace) {
4964
- const distance = distanceBetweenPoints(origin.x, origin.y, x, y);
4965
- if (Number(distance) <= Number(maxDistance)) {
4966
- const system = hasSystem(seed, { x, y });
4967
- if (system) {
4968
- nearbySystems.push({ origin, destination: { x, y }, distance });
4969
- }
4970
- }
4971
- }
4972
- }
4973
- }
4974
- return nearbySystems;
4975
- }
4976
- function calc_rechargetime(capacity, energy, recharge) {
4977
- const cap = UInt32.from(capacity);
4978
- const eng = UInt32.from(energy);
4979
- if (eng.gte(cap))
4980
- return UInt32.zero;
4981
- return cap.subtracting(eng).dividing(recharge);
4982
- }
4983
- function calc_ship_rechargetime(ship) {
4984
- if (!ship.generator)
4985
- return UInt32.from(0);
4986
- return calc_rechargetime(ship.generator.capacity, ship.energy ?? UInt16.from(0), ship.generator.recharge);
4987
- }
4988
- function calc_flighttime(distance, acceleration) {
4989
- return UInt32.from(2 * Math.sqrt(Number(distance) / acceleration));
4990
- }
4991
- function calc_loader_flighttime(ship, mass, altitude) {
4992
- const z = altitude ?? ship.coordinates.z?.toNumber() ?? calc_orbital_altitude(Number(mass));
4993
- return calc_flighttime(z, calc_loader_acceleration(ship, mass));
4994
- }
4995
- function calc_loader_acceleration(ship, mass) {
4996
- const thrust = ship.loaders ? Number(ship.loaders.thrust) : 0;
4997
- const loaderMass = ship.loaders ? Number(ship.loaders.mass) : 0;
4998
- return calc_acceleration(thrust, Number(mass) + loaderMass);
4999
- }
5000
- function calc_ship_flighttime(ship, mass, distance) {
5001
- const acceleration = calc_ship_acceleration(ship, mass);
5002
- return calc_flighttime(distance, acceleration);
5003
- }
5004
- function calc_ship_acceleration(ship, mass) {
5005
- const thrust = ship.engines ? Number(ship.engines.thrust) : 0;
5006
- return calc_acceleration(thrust, Number(mass));
5007
- }
5008
- function calc_acceleration(thrust, mass) {
5009
- return (thrust / mass) * PRECISION$1;
5010
- }
5011
- function calc_ship_mass(ship, cargos) {
5012
- const mass = UInt64.from(0);
5013
- mass.add(ship.hullmass);
5014
- if (ship.loaders && ship.loaders.quantity.gt(UInt32.zero)) {
5015
- mass.add(ship.loaders.mass.multiplying(ship.loaders.quantity));
5016
- }
5017
- for (const cargo of cargos) {
5018
- mass.add(getItem(cargo.item_id).mass.multiplying(cargo.quantity));
5019
- }
5020
- return mass;
5021
- }
5022
- function calc_energyusage(distance, drain) {
5023
- return UInt64.from(distance).dividing(PRECISION$1).multiplying(drain);
5024
- }
5025
- function calculateTransferTime(ship, cargos, quantities) {
5026
- let mass = UInt64.from(0);
5027
- for (const cargo of cargos) {
5028
- const qty = quantities?.get(Number(cargo.item_id)) ?? 0;
5029
- if (qty > 0) {
5030
- const good_mass = getItem(cargo.item_id).mass;
5031
- const cargo_mass = good_mass.multiplying(qty);
5032
- mass = UInt64.from(mass).adding(cargo_mass);
5033
- }
5034
- }
5035
- if (mass.equals(UInt64.zero)) {
5036
- return UInt32.from(0);
5037
- }
5038
- if (!ship.loaders)
5039
- return UInt32.from(0);
5040
- mass = UInt64.from(mass).adding(ship.loaders.mass);
5041
- const transfer_time = calc_loader_flighttime(ship, mass);
5042
- return transfer_time.dividing(ship.loaders.quantity);
5043
- }
5044
- function calculateRefuelingTime(ship) {
5045
- return calc_ship_rechargetime(ship);
5046
- }
5047
- function calculateFlightTime(ship, cargos, distance) {
5048
- const mass = calc_ship_mass(ship, cargos);
5049
- return calc_ship_flighttime(ship, mass, distance);
5050
- }
5051
- function calculateLoadTimeBreakdown(ship, cargos, loadQuantities, unloadQuantities) {
5052
- let mass_unload = UInt64.from(0);
5053
- let mass_load = UInt64.from(0);
5054
- for (const cargo of cargos) {
5055
- const goodId = Number(cargo.item_id);
5056
- const loadQty = loadQuantities?.get(goodId) ?? 0;
5057
- const unloadQty = unloadQuantities?.get(goodId) ?? 0;
5058
- if (loadQty > 0 || unloadQty > 0) {
5059
- const good = getItem(cargo.item_id);
5060
- if (loadQty > 0) {
5061
- const cargo_mass = good.mass.multiplying(loadQty);
5062
- mass_load = UInt64.from(mass_load).adding(cargo_mass);
5063
- }
5064
- if (unloadQty > 0) {
5065
- const cargo_mass = good.mass.multiplying(unloadQty);
5066
- mass_unload = UInt64.from(mass_unload).adding(cargo_mass);
5067
- }
5068
- }
5069
- }
5070
- let unloadTime = 0;
5071
- let loadTime = 0;
5072
- if (mass_unload.gt(UInt64.zero) && ship.loaders) {
5073
- const totalMass = UInt64.from(mass_unload).adding(ship.loaders.mass);
5074
- unloadTime = Number(calc_loader_flighttime(ship, totalMass));
5075
- }
5076
- if (mass_load.gt(UInt64.zero) && ship.loaders) {
5077
- const totalMass = UInt64.from(mass_load).adding(ship.loaders.mass);
5078
- loadTime = Number(calc_loader_flighttime(ship, totalMass));
5079
- }
5080
- const numLoaders = ship.loaders ? Number(ship.loaders.quantity) : 0;
5081
- const totalTime = numLoaders > 0 ? (unloadTime + loadTime) / numLoaders : 0;
5082
- const unloadTimePerLoader = numLoaders > 0 ? unloadTime / numLoaders : 0;
5083
- const loadTimePerLoader = numLoaders > 0 ? loadTime / numLoaders : 0;
5084
- return {
5085
- unloadTime: unloadTimePerLoader,
5086
- loadTime: loadTimePerLoader,
5087
- totalTime,
5088
- unloadMass: Number(mass_unload),
5089
- loadMass: Number(mass_load),
5090
- };
4908
+ const ITEM_ENGINE_T1 = 10100;
4909
+ const ITEM_GENERATOR_T1 = 10101;
4910
+ const ITEM_GATHERER_T1 = 10102;
4911
+ const ITEM_LOADER_T1 = 10103;
4912
+ const ITEM_MANUFACTURING_T1 = 10104;
4913
+ const ITEM_STORAGE_T1 = 10105;
4914
+ const ITEM_HAULER_T1 = 10106;
4915
+ const MODULE_ANY = 0;
4916
+ const MODULE_ENGINE = 1;
4917
+ const MODULE_GENERATOR = 2;
4918
+ const MODULE_GATHERER = 3;
4919
+ const MODULE_LOADER = 4;
4920
+ const MODULE_WARP = 5;
4921
+ const MODULE_CRAFTER = 6;
4922
+ const MODULE_LAUNCHER = 7;
4923
+ const MODULE_STORAGE = 8;
4924
+ const MODULE_HAULER = 9;
4925
+ function moduleAccepts(slotType, moduleType) {
4926
+ return slotType === MODULE_ANY || slotType === moduleType;
5091
4927
  }
5092
- function estimateTravelTime(ship, travelMass, distance, options = {}) {
5093
- const { needsRecharge = false, loadMass, unloadMass } = options;
5094
- const flightTime = calc_ship_flighttime(ship, UInt64.from(travelMass), UInt64.from(distance));
5095
- const rechargeTime = needsRecharge ? calc_ship_rechargetime(ship) : UInt32.zero;
5096
- let loadTime = UInt32.zero;
5097
- let unloadTime = UInt32.zero;
5098
- if (loadMass &&
5099
- UInt32.from(loadMass).gt(UInt32.zero) &&
5100
- ship.loaders &&
5101
- ship.loaders.quantity.gt(UInt32.zero)) {
5102
- const totalMass = UInt64.from(loadMass).adding(ship.loaders.mass);
5103
- loadTime = calc_loader_flighttime(ship, totalMass).dividing(ship.loaders.quantity);
5104
- }
5105
- if (unloadMass &&
5106
- UInt32.from(unloadMass).gt(UInt32.zero) &&
5107
- ship.loaders &&
5108
- ship.loaders.quantity.gt(UInt32.zero)) {
5109
- const totalMass = UInt64.from(unloadMass).adding(ship.loaders.mass);
5110
- unloadTime = calc_loader_flighttime(ship, totalMass).dividing(ship.loaders.quantity);
4928
+ function getModuleCapabilityType(itemId) {
4929
+ switch (itemId) {
4930
+ case ITEM_ENGINE_T1:
4931
+ return MODULE_ENGINE;
4932
+ case ITEM_GENERATOR_T1:
4933
+ return MODULE_GENERATOR;
4934
+ case ITEM_GATHERER_T1:
4935
+ return MODULE_GATHERER;
4936
+ case ITEM_LOADER_T1:
4937
+ return MODULE_LOADER;
4938
+ case ITEM_MANUFACTURING_T1:
4939
+ return MODULE_CRAFTER;
4940
+ case ITEM_STORAGE_T1:
4941
+ return MODULE_STORAGE;
4942
+ case ITEM_HAULER_T1:
4943
+ return MODULE_HAULER;
4944
+ default:
4945
+ return 0xff;
5111
4946
  }
5112
- return {
5113
- flightTime,
5114
- rechargeTime,
5115
- loadTime,
5116
- unloadTime,
5117
- total: flightTime.adding(rechargeTime).adding(loadTime).adding(unloadTime),
5118
- };
5119
- }
5120
- function estimateDealTravelTime(ship, shipMass, distance, loadMass) {
5121
- const needsRecharge = !hasEnergyForDistance$1(ship, distance);
5122
- const estimate = estimateTravelTime(ship, shipMass, distance, {
5123
- needsRecharge,
5124
- loadMass,
5125
- });
5126
- return estimate.total;
5127
4947
  }
5128
- function hasEnergyForDistance$1(ship, distance) {
5129
- if (!ship.engines)
5130
- return false;
5131
- const energyNeeded = UInt64.from(distance).dividing(PRECISION$1).multiplying(ship.engines.drain);
5132
- return UInt64.from(ship.energy ?? 0).gte(energyNeeded);
5133
- }
5134
- function getFlightOrigin(entity, flightTaskIndex) {
5135
- if (!entity.schedule)
5136
- return entity.coordinates;
5137
- let origin = entity.coordinates;
5138
- for (let i = 0; i < flightTaskIndex && i < entity.schedule.tasks.length; i++) {
5139
- const task = entity.schedule.tasks[i];
5140
- if (task.type.equals(TaskType.TRAVEL) && task.coordinates) {
5141
- origin = task.coordinates;
5142
- }
5143
- }
5144
- return origin;
5145
- }
5146
- function getDestinationLocation(entity) {
5147
- if (!entity.schedule)
5148
- return undefined;
5149
- for (let i = entity.schedule.tasks.length - 1; i >= 0; i--) {
5150
- const task = entity.schedule.tasks[i];
5151
- if (task.type.equals(TaskType.TRAVEL) && task.coordinates) {
5152
- return task.coordinates;
5153
- }
5154
- }
5155
- return undefined;
5156
- }
5157
- function getPositionAt(entity, taskIndex, taskProgress) {
5158
- if (!entity.schedule || entity.schedule.tasks.length === 0 || taskIndex < 0) {
5159
- return entity.coordinates;
5160
- }
5161
- const task = entity.schedule.tasks[taskIndex];
5162
- if (!task.type.equals(TaskType.TRAVEL) || !task.coordinates) {
5163
- return getFlightOrigin(entity, taskIndex);
5164
- }
5165
- const origin = getFlightOrigin(entity, taskIndex);
5166
- const destination = task.coordinates;
5167
- const interpolated = lerp(origin, destination, taskProgress);
5168
- return {
5169
- x: Math.round(interpolated.x),
5170
- y: Math.round(interpolated.y),
5171
- };
5172
- }
5173
- function calc_transfer_duration(source, dest, cargoMass) {
5174
- if (cargoMass === 0) {
5175
- return 0;
5176
- }
5177
- let totalThrust = 0;
5178
- let totalLoaderMass = 0;
5179
- let totalQuantity = 0;
5180
- if (source.loaders) {
5181
- const thrust = typeof source.loaders.thrust === 'number'
5182
- ? source.loaders.thrust
5183
- : source.loaders.thrust.toNumber();
5184
- const mass = typeof source.loaders.mass === 'number'
5185
- ? source.loaders.mass
5186
- : source.loaders.mass.toNumber();
5187
- const qty = typeof source.loaders.quantity === 'number'
5188
- ? source.loaders.quantity
5189
- : source.loaders.quantity.toNumber();
5190
- totalThrust += thrust * qty;
5191
- totalLoaderMass += mass * qty;
5192
- totalQuantity += qty;
5193
- }
5194
- if (dest.loaders) {
5195
- const thrust = typeof dest.loaders.thrust === 'number'
5196
- ? dest.loaders.thrust
5197
- : dest.loaders.thrust.toNumber();
5198
- const mass = typeof dest.loaders.mass === 'number' ? dest.loaders.mass : dest.loaders.mass.toNumber();
5199
- const qty = typeof dest.loaders.quantity === 'number'
5200
- ? dest.loaders.quantity
5201
- : dest.loaders.quantity.toNumber();
5202
- totalThrust += thrust * qty;
5203
- totalLoaderMass += mass * qty;
5204
- totalQuantity += qty;
5205
- }
5206
- if (totalThrust === 0 || totalQuantity === 0) {
5207
- return 0;
5208
- }
5209
- const sourceZ = typeof source.location.z === 'number'
5210
- ? source.location.z
5211
- : source.location.z?.toNumber() ?? 0;
5212
- const destZ = typeof dest.location.z === 'number' ? dest.location.z : dest.location.z?.toNumber() ?? 0;
5213
- const distance = Math.abs(sourceZ - destZ);
5214
- const totalMass = cargoMass + totalLoaderMass;
5215
- const acceleration = calc_acceleration(totalThrust, totalMass);
5216
- const flightTime = 2 * Math.sqrt(distance / acceleration);
5217
- return Math.floor(flightTime / totalQuantity);
5218
- }
5219
-
5220
- function capsHasMovement(caps) {
5221
- return caps.engines !== undefined && caps.generator !== undefined;
5222
- }
5223
- function capsHasStorage(caps) {
5224
- return caps.capacity !== undefined;
5225
- }
5226
- function capsHasLoaders(caps) {
5227
- return caps.loaders !== undefined;
5228
- }
5229
- function capsHasGatherer(caps) {
5230
- return caps.gatherer !== undefined;
5231
- }
5232
- function capsHasMass(caps) {
5233
- return caps.hullmass !== undefined;
5234
- }
5235
-
5236
- function calcCargoItemMass(item) {
5237
- const itemDef = getItem(item.item_id);
5238
- let mass = UInt64.from(itemDef.mass).multiplying(item.quantity);
5239
- for (const mod of item.modules) {
5240
- if (mod.installed) {
5241
- const modDef = getItem(mod.installed.item_id);
5242
- mass = mass.adding(modDef.mass);
5243
- }
5244
- }
5245
- return mass;
5246
- }
5247
- function calcCargoMass(entity) {
5248
- let mass = UInt64.from(0);
5249
- for (const item of entity.cargo) {
5250
- mass = mass.adding(calcCargoItemMass(item));
5251
- }
5252
- return mass;
5253
- }
5254
- function availableCapacity$1(entity) {
5255
- const cargoMass = calcCargoMass(entity);
5256
- return entity.capacity.gt(cargoMass)
5257
- ? UInt64.from(entity.capacity).subtracting(cargoMass)
5258
- : UInt64.from(0);
5259
- }
5260
- function availableCapacityFromMass(capacity, cargoMass) {
5261
- const cap = UInt64.from(capacity);
5262
- const mass = UInt64.from(cargoMass);
5263
- return cap.gt(mass) ? cap.subtracting(mass) : UInt64.from(0);
5264
- }
5265
- function hasSpace$1(entity, goodMass, quantity) {
5266
- const additional = goodMass.multiplying(quantity);
5267
- return availableCapacity$1(entity).gte(additional);
5268
- }
5269
- function hasSpaceForMass(capacity, currentMass, additionalMass) {
5270
- return UInt64.from(currentMass).adding(additionalMass).lte(capacity);
5271
- }
5272
- function isFull$1(entity) {
5273
- return UInt64.from(entity.cargomass).gte(entity.capacity);
5274
- }
5275
- function isFullFromMass(capacity, cargoMass) {
5276
- return UInt64.from(cargoMass).gte(capacity);
5277
- }
5278
-
5279
- function hasSchedule$1(entity) {
5280
- return !!entity.schedule && entity.schedule.tasks.length > 0;
5281
- }
5282
- function isIdle(entity) {
5283
- return !hasSchedule$1(entity);
5284
- }
5285
- function getTasks(entity) {
5286
- return entity.schedule?.tasks || [];
5287
- }
5288
- function scheduleDuration(entity) {
5289
- if (!entity.schedule)
5290
- return 0;
5291
- return entity.schedule.tasks.reduce((sum, task) => sum + task.duration.toNumber(), 0);
5292
- }
5293
- function scheduleElapsed(entity, now) {
5294
- if (!entity.schedule)
5295
- return 0;
5296
- const started = entity.schedule.started.toDate();
5297
- const elapsed = Math.floor((now.getTime() - started.getTime()) / 1000);
5298
- return Math.max(0, elapsed);
5299
- }
5300
- function scheduleRemaining(entity, now) {
5301
- if (!entity.schedule)
5302
- return 0;
5303
- const duration = scheduleDuration(entity);
5304
- const elapsed = scheduleElapsed(entity, now);
5305
- return Math.max(0, duration - elapsed);
5306
- }
5307
- function scheduleComplete(entity, now) {
5308
- return hasSchedule$1(entity) && scheduleRemaining(entity, now) === 0;
5309
- }
5310
- function currentTaskIndex(entity, now) {
5311
- if (!entity.schedule || entity.schedule.tasks.length === 0)
5312
- return -1;
5313
- const elapsed = scheduleElapsed(entity, now);
5314
- let timeAccum = 0;
5315
- for (let i = 0; i < entity.schedule.tasks.length; i++) {
5316
- const taskDuration = entity.schedule.tasks[i].duration.toNumber();
5317
- if (elapsed < timeAccum + taskDuration) {
5318
- return i;
5319
- }
5320
- timeAccum += taskDuration;
5321
- }
5322
- return entity.schedule.tasks.length - 1;
5323
- }
5324
- function currentTask(entity, now) {
5325
- const index = currentTaskIndex(entity, now);
5326
- if (index < 0 || !entity.schedule)
5327
- return undefined;
5328
- return entity.schedule.tasks[index];
5329
- }
5330
- function currentTaskType(entity, now) {
5331
- const task = currentTask(entity, now);
5332
- if (!task)
5333
- return undefined;
5334
- return task.type.toNumber();
5335
- }
5336
- function getTaskStartTime(entity, index) {
5337
- if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length)
5338
- return 0;
5339
- let timeAccum = 0;
5340
- for (let i = 0; i < index; i++) {
5341
- timeAccum += entity.schedule.tasks[i].duration.toNumber();
5342
- }
5343
- return timeAccum;
5344
- }
5345
- function getTaskElapsed(entity, index, now) {
5346
- if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length)
5347
- return 0;
5348
- const elapsed = scheduleElapsed(entity, now);
5349
- const taskStart = getTaskStartTime(entity, index);
5350
- const taskDuration = entity.schedule.tasks[index].duration.toNumber();
5351
- if (elapsed <= taskStart)
5352
- return 0;
5353
- const elapsedInTask = elapsed - taskStart;
5354
- return Math.min(elapsedInTask, taskDuration);
5355
- }
5356
- function getTaskRemaining(entity, index, now) {
5357
- if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length)
5358
- return 0;
5359
- const taskDuration = entity.schedule.tasks[index].duration.toNumber();
5360
- const taskElapsed = getTaskElapsed(entity, index, now);
5361
- return Math.max(0, taskDuration - taskElapsed);
5362
- }
5363
- function isTaskComplete(entity, index, now) {
5364
- if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length)
5365
- return false;
5366
- const taskDuration = entity.schedule.tasks[index].duration.toNumber();
5367
- const taskElapsed = getTaskElapsed(entity, index, now);
5368
- return taskElapsed >= taskDuration;
5369
- }
5370
- function isTaskInProgress(entity, index, now) {
5371
- if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length)
5372
- return false;
5373
- const taskElapsed = getTaskElapsed(entity, index, now);
5374
- const taskDuration = entity.schedule.tasks[index].duration.toNumber();
5375
- return taskElapsed > 0 && taskElapsed < taskDuration;
5376
- }
5377
- function currentTaskProgress(entity, now) {
5378
- const task = currentTask(entity, now);
5379
- if (!task)
5380
- return 0;
5381
- const index = currentTaskIndex(entity, now);
5382
- const elapsed = getTaskElapsed(entity, index, now);
5383
- const duration = task.duration.toNumber();
5384
- if (duration === 0)
5385
- return 1;
5386
- return Math.min(1, elapsed / duration);
5387
- }
5388
- function scheduleProgress(entity, now) {
5389
- const duration = scheduleDuration(entity);
5390
- if (duration === 0)
5391
- return hasSchedule$1(entity) ? 1 : 0;
5392
- const elapsed = scheduleElapsed(entity, now);
5393
- return Math.min(1, elapsed / duration);
5394
- }
5395
- function isTaskType(entity, taskType, now) {
5396
- return currentTaskType(entity, now) === taskType;
5397
- }
5398
- function isInFlight(entity, now) {
5399
- return isTaskType(entity, TaskType.TRAVEL, now);
5400
- }
5401
- function isRecharging(entity, now) {
5402
- return isTaskType(entity, TaskType.RECHARGE, now);
5403
- }
5404
- function isLoading(entity, now) {
5405
- return isTaskType(entity, TaskType.LOAD, now);
5406
- }
5407
- function isUnloading(entity, now) {
5408
- return isTaskType(entity, TaskType.UNLOAD, now);
5409
- }
5410
- function isGathering(entity, now) {
5411
- return isTaskType(entity, TaskType.GATHER, now);
5412
- }
5413
-
5414
- var schedule = /*#__PURE__*/Object.freeze({
5415
- __proto__: null,
5416
- hasSchedule: hasSchedule$1,
5417
- isIdle: isIdle,
5418
- getTasks: getTasks,
5419
- scheduleDuration: scheduleDuration,
5420
- scheduleElapsed: scheduleElapsed,
5421
- scheduleRemaining: scheduleRemaining,
5422
- scheduleComplete: scheduleComplete,
5423
- currentTaskIndex: currentTaskIndex,
5424
- currentTask: currentTask,
5425
- currentTaskType: currentTaskType,
5426
- getTaskStartTime: getTaskStartTime,
5427
- getTaskElapsed: getTaskElapsed,
5428
- getTaskRemaining: getTaskRemaining,
5429
- isTaskComplete: isTaskComplete,
5430
- isTaskInProgress: isTaskInProgress,
5431
- currentTaskProgress: currentTaskProgress,
5432
- scheduleProgress: scheduleProgress,
5433
- isTaskType: isTaskType,
5434
- isInFlight: isInFlight,
5435
- isRecharging: isRecharging,
5436
- isLoading: isLoading,
5437
- isUnloading: isUnloading,
5438
- isGathering: isGathering
5439
- });
5440
-
5441
- function getHullMass(entity) {
5442
- return UInt32.from(entity.hullmass ?? 0);
5443
- }
5444
- function createProjectedEntity(entity) {
5445
- const cargoMass = calcCargoMass(entity);
5446
- const shipMass = getHullMass(entity);
5447
- const loaders = entity.loaders;
5448
- const engines = entity.engines;
5449
- const generator = entity.generator;
5450
- const hauler = entity.hauler;
5451
- const capacity = entity.capacity;
5452
- const projected = {
5453
- location: Coordinates.from(entity.coordinates),
5454
- energy: UInt16.from(entity.energy ?? 0),
5455
- cargoMass,
5456
- shipMass,
5457
- capacity: capacity ? UInt64.from(capacity) : undefined,
5458
- engines,
5459
- generator,
5460
- hauler,
5461
- loaders,
5462
- get totalMass() {
5463
- let mass = UInt64.from(this.shipMass).adding(this.cargoMass);
5464
- if (this.loaders) {
5465
- mass = mass.adding(this.loaders.mass.multiplying(this.loaders.quantity));
5466
- }
5467
- return mass;
5468
- },
5469
- hasMovement() {
5470
- return capsHasMovement(this.capabilities());
5471
- },
5472
- hasStorage() {
5473
- return capsHasStorage(this.capabilities());
5474
- },
5475
- hasLoaders() {
5476
- return capsHasLoaders(this.capabilities());
5477
- },
5478
- capabilities() {
5479
- return {
5480
- hullmass: this.shipMass,
5481
- capacity: this.capacity ? UInt32.from(this.capacity) : undefined,
5482
- engines: this.engines,
5483
- generator: this.generator,
5484
- loaders: this.loaders,
5485
- };
5486
- },
5487
- state() {
5488
- return {
5489
- owner: entity.owner ?? Name.from(''),
5490
- location: Types.coordinates.from(this.location),
5491
- energy: this.energy,
5492
- cargomass: UInt32.from(this.cargoMass),
5493
- cargo: entity.cargo,
5494
- };
5495
- },
5496
- };
5497
- return projected;
5498
- }
5499
- function applyRechargeTask(projected, _task, options) {
5500
- if (!projected.generator)
5501
- return;
5502
- if (options.complete) {
5503
- projected.energy = UInt16.from(projected.generator.capacity);
5504
- }
5505
- else if (options.progress !== undefined) {
5506
- const capacity = Number(projected.generator.capacity);
5507
- const currentEnergy = Number(projected.energy);
5508
- const rechargeAmount = (capacity - currentEnergy) * options.progress;
5509
- projected.energy = UInt16.from(Math.min(capacity, currentEnergy + rechargeAmount));
5510
- }
5511
- }
5512
- function applyFlightTask(projected, task, options) {
5513
- if (!task.coordinates || !projected.engines)
5514
- return;
5515
- const origin = projected.location;
5516
- const destination = Coordinates.from(task.coordinates);
5517
- const distance = distanceBetweenCoordinates(origin, task.coordinates);
5518
- const energyUsage = distance.dividing(PRECISION$1).multiplying(projected.engines.drain);
5519
- if (options.complete) {
5520
- projected.energy = projected.energy.gt(energyUsage)
5521
- ? UInt16.from(projected.energy.subtracting(energyUsage))
5522
- : UInt16.from(0);
5523
- projected.location = destination;
5524
- }
5525
- else if (options.progress !== undefined) {
5526
- const interpolated = lerp(origin, destination, options.progress);
5527
- projected.location = Coordinates.from({
5528
- x: Math.round(interpolated.x),
5529
- y: Math.round(interpolated.y),
5530
- });
5531
- const partialEnergy = UInt64.from(Math.floor(Number(energyUsage) * options.progress));
5532
- projected.energy = projected.energy.gt(partialEnergy)
5533
- ? UInt16.from(projected.energy.subtracting(partialEnergy))
5534
- : UInt16.from(0);
5535
- }
5536
- }
5537
- function applyLoadTask(projected, task) {
5538
- for (const item of task.cargo) {
5539
- projected.cargoMass = projected.cargoMass.adding(calcCargoItemMass(item));
5540
- }
5541
- }
5542
- function applyUnloadTask(projected, task) {
5543
- for (const item of task.cargo) {
5544
- const cargoMass = calcCargoItemMass(item);
5545
- projected.cargoMass = projected.cargoMass.gt(cargoMass)
5546
- ? projected.cargoMass.subtracting(cargoMass)
5547
- : UInt64.from(0);
5548
- }
5549
- }
5550
- function applyEnergyCost(projected, task) {
5551
- if (!task.energy_cost)
5552
- return;
5553
- const energyCost = UInt16.from(task.energy_cost);
5554
- projected.energy = projected.energy.gt(energyCost)
5555
- ? UInt16.from(projected.energy.subtracting(energyCost))
5556
- : UInt16.from(0);
5557
- }
5558
- function applyGatherTask(projected, task, options) {
5559
- if (!options.complete)
5560
- return;
5561
- applyEnergyCost(projected, task);
5562
- for (const item of task.cargo) {
5563
- projected.cargoMass = projected.cargoMass.adding(calcCargoItemMass(item));
5564
- }
5565
- }
5566
- function applyCraftTask(projected, task) {
5567
- applyEnergyCost(projected, task);
5568
- if (task.cargo.length > 0) {
5569
- for (let i = 0; i < task.cargo.length - 1; i++) {
5570
- const inputMass = calcCargoItemMass(task.cargo[i]);
5571
- projected.cargoMass = projected.cargoMass.gt(inputMass)
5572
- ? projected.cargoMass.subtracting(inputMass)
5573
- : UInt64.from(0);
5574
- }
5575
- const output = task.cargo[task.cargo.length - 1];
5576
- projected.cargoMass = projected.cargoMass.adding(calcCargoItemMass(output));
5577
- }
5578
- }
5579
- function applyDeployTask(projected, task) {
5580
- applyEnergyCost(projected, task);
5581
- if (task.cargo.length > 0) {
5582
- const mass = calcCargoItemMass(task.cargo[0]);
5583
- projected.cargoMass = projected.cargoMass.gt(mass)
5584
- ? projected.cargoMass.subtracting(mass)
5585
- : UInt64.from(0);
5586
- }
5587
- }
5588
- function projectEntity(entity) {
5589
- const projected = createProjectedEntity(entity);
5590
- if (!entity.schedule) {
5591
- return projected;
5592
- }
5593
- for (const task of entity.schedule.tasks) {
5594
- switch (task.type.toNumber()) {
5595
- case TaskType.RECHARGE:
5596
- applyRechargeTask(projected, task, { complete: true });
5597
- break;
5598
- case TaskType.TRAVEL:
5599
- applyFlightTask(projected, task, { complete: true });
5600
- break;
5601
- case TaskType.LOAD:
5602
- applyLoadTask(projected, task);
5603
- break;
5604
- case TaskType.UNLOAD:
5605
- applyUnloadTask(projected, task);
5606
- break;
5607
- case TaskType.GATHER:
5608
- applyGatherTask(projected, task, { complete: true });
5609
- break;
5610
- case TaskType.CRAFT:
5611
- applyCraftTask(projected, task);
5612
- break;
5613
- case TaskType.DEPLOY:
5614
- case TaskType.DEPLOY_SHIP:
5615
- applyDeployTask(projected, task);
5616
- break;
5617
- }
5618
- }
5619
- return projected;
5620
- }
5621
- function projectEntityAt(entity, now) {
5622
- const projected = createProjectedEntity(entity);
5623
- if (!entity.schedule || entity.schedule.tasks.length === 0) {
5624
- return projected;
5625
- }
5626
- for (let i = 0; i < entity.schedule.tasks.length; i++) {
5627
- const task = entity.schedule.tasks[i];
5628
- const taskComplete = isTaskComplete(entity, i, now);
5629
- const taskInProgress = isTaskInProgress(entity, i, now);
5630
- if (!taskComplete && !taskInProgress) {
5631
- break;
5632
- }
5633
- const progress = taskInProgress
5634
- ? getTaskElapsed(entity, i, now) / task.duration.toNumber()
5635
- : undefined;
5636
- switch (task.type.toNumber()) {
5637
- case TaskType.RECHARGE:
5638
- applyRechargeTask(projected, task, { complete: taskComplete, progress });
5639
- break;
5640
- case TaskType.TRAVEL:
5641
- applyFlightTask(projected, task, { complete: taskComplete, progress });
5642
- break;
5643
- case TaskType.LOAD:
5644
- if (taskComplete) {
5645
- applyLoadTask(projected, task);
5646
- }
5647
- break;
5648
- case TaskType.UNLOAD:
5649
- if (taskComplete) {
5650
- applyUnloadTask(projected, task);
5651
- }
5652
- break;
5653
- case TaskType.GATHER:
5654
- if (taskComplete) {
5655
- applyGatherTask(projected, task, { complete: true });
5656
- }
5657
- break;
5658
- case TaskType.CRAFT:
5659
- if (taskComplete) {
5660
- applyCraftTask(projected, task);
5661
- }
5662
- break;
5663
- case TaskType.DEPLOY:
5664
- case TaskType.DEPLOY_SHIP:
5665
- if (taskComplete) {
5666
- applyDeployTask(projected, task);
5667
- }
5668
- break;
5669
- }
5670
- }
5671
- return projected;
5672
- }
5673
-
5674
- class Location {
5675
- constructor(coordinates) {
5676
- this.coordinates = Coordinates.from(coordinates);
5677
- }
5678
- static from(coordinates) {
5679
- return new Location(Coordinates.from(coordinates));
5680
- }
5681
- hasSystemAt(gameSeed) {
5682
- const seed = Checksum256.from(gameSeed);
5683
- if (this._hasSystem === undefined || !this._gameSeed?.equals(seed)) {
5684
- this._gameSeed = seed;
5685
- this._hasSystem = hasSystem(seed, this.coordinates);
5686
- }
5687
- return this._hasSystem;
5688
- }
5689
- getLocationTypeAt(gameSeed) {
5690
- return getLocationType(gameSeed, this.coordinates);
5691
- }
5692
- isGatherableAt(gameSeed) {
5693
- return isGatherableLocation(this.getLocationTypeAt(gameSeed));
5694
- }
5695
- findNearby(gameSeed, maxDistance = 20) {
5696
- return findNearbyPlanets(Checksum256.from(gameSeed), this.coordinates, maxDistance);
5697
- }
5698
- equals(other) {
5699
- const otherCoords = other instanceof Location ? other.coordinates : Coordinates.from(other);
5700
- return this.coordinates.equals(otherCoords);
5701
- }
5702
- get epoch() {
5703
- return this._epoch;
5704
- }
5705
- clearCache() {
5706
- this._epoch = undefined;
5707
- }
5708
- }
5709
- function toLocation(coords) {
5710
- if (coords instanceof Location) {
5711
- return coords;
5712
- }
5713
- return Location.from(coords);
5714
- }
5715
-
5716
- class ScheduleAccessor {
5717
- constructor(entity) {
5718
- this.entity = entity;
5719
- }
5720
- get hasSchedule() {
5721
- return hasSchedule$1(this.entity);
5722
- }
5723
- get isIdle() {
5724
- return isIdle(this.entity);
5725
- }
5726
- get tasks() {
5727
- return getTasks(this.entity);
5728
- }
5729
- duration() {
5730
- return scheduleDuration(this.entity);
5731
- }
5732
- elapsed(now) {
5733
- return scheduleElapsed(this.entity, now);
5734
- }
5735
- remaining(now) {
5736
- return scheduleRemaining(this.entity, now);
5737
- }
5738
- complete(now) {
5739
- return scheduleComplete(this.entity, now);
5740
- }
5741
- currentTaskIndex(now) {
5742
- return currentTaskIndex(this.entity, now);
5743
- }
5744
- currentTask(now) {
5745
- return currentTask(this.entity, now);
5746
- }
5747
- currentTaskType(now) {
5748
- return currentTaskType(this.entity, now);
5749
- }
5750
- taskStartTime(index) {
5751
- return getTaskStartTime(this.entity, index);
5752
- }
5753
- taskElapsed(index, now) {
5754
- return getTaskElapsed(this.entity, index, now);
5755
- }
5756
- taskRemaining(index, now) {
5757
- return getTaskRemaining(this.entity, index, now);
5758
- }
5759
- taskComplete(index, now) {
5760
- return isTaskComplete(this.entity, index, now);
5761
- }
5762
- taskInProgress(index, now) {
5763
- return isTaskInProgress(this.entity, index, now);
5764
- }
5765
- currentTaskProgress(now) {
5766
- return currentTaskProgress(this.entity, now);
5767
- }
5768
- progress(now) {
5769
- return scheduleProgress(this.entity, now);
5770
- }
5771
- }
5772
- function createScheduleAccessor(entity) {
5773
- return new ScheduleAccessor(entity);
5774
- }
5775
-
5776
- class EntityInventory extends Types.cargo_item {
5777
- get item() {
5778
- if (!this._item) {
5779
- this._item = getItem(this.item_id);
5780
- }
5781
- return this._item;
5782
- }
5783
- get good() {
5784
- return this.item;
5785
- }
5786
- get name() {
5787
- return this.item.name;
5788
- }
5789
- get unitMass() {
5790
- return this.item.mass;
5791
- }
5792
- get totalMass() {
5793
- return UInt64.from(this.unitMass).multiplying(this.quantity);
5794
- }
5795
- get hasCargo() {
5796
- return UInt32.from(this.quantity).gt(UInt32.from(0));
5797
- }
5798
- get isEmpty() {
5799
- return UInt32.from(this.quantity).equals(UInt32.from(0));
5800
- }
5801
- }
5802
-
5803
- class InventoryAccessor {
5804
- constructor(entity) {
5805
- this.entity = entity;
5806
- }
5807
- get items() {
5808
- if (!this._items) {
5809
- this._items = this.entity.cargo.map((item) => new EntityInventory(item));
5810
- }
5811
- return this._items;
5812
- }
5813
- get totalMass() {
5814
- return this.items.reduce((sum, c) => sum.adding(c.totalMass), UInt64.from(0));
5815
- }
5816
- forItem(goodId) {
5817
- return this.items.find((c) => c.item_id.equals(goodId));
5818
- }
5819
- get sellable() {
5820
- return this.items.filter((c) => c.hasCargo);
5821
- }
5822
- get hasSellable() {
5823
- return this.items.some((c) => c.hasCargo);
5824
- }
5825
- get sellableCount() {
5826
- return this.items.filter((c) => c.hasCargo).length;
5827
- }
5828
- }
5829
- function createInventoryAccessor(entity) {
5830
- return new InventoryAccessor(entity);
5831
- }
5832
-
5833
- function maxTravelDistance(entity) {
5834
- return UInt32.from(entity.generator.capacity)
5835
- .dividing(entity.engines.drain)
5836
- .multiplying(PRECISION$1);
5837
- }
5838
- function calcEnergyUsage(entity, distance) {
5839
- return distance.dividing(PRECISION$1).multiplying(entity.engines.drain);
5840
- }
5841
- function hasEnergyForDistance(entity, distance) {
5842
- const usage = calcEnergyUsage(entity, distance);
5843
- return UInt64.from(entity.energy).gte(usage);
5844
- }
5845
- function energyPercent(entity) {
5846
- return (Number(entity.energy) / Number(entity.generator.capacity)) * 100;
5847
- }
5848
- function needsRecharge(entity) {
5849
- return UInt64.from(entity.energy).lt(entity.generator.capacity);
5850
- }
5851
-
5852
- class Ship extends Types.entity_info {
5853
- get name() {
5854
- return this.entity_name;
5855
- }
5856
- get inv() {
5857
- return (this._inv ?? (this._inv = new InventoryAccessor(this)));
5858
- }
5859
- get inventory() {
5860
- return this.inv.items;
5861
- }
5862
- get sched() {
5863
- return (this._sched ?? (this._sched = new ScheduleAccessor(this)));
5864
- }
5865
- get maxDistance() {
5866
- if (!this.generator || !this.engines)
5867
- return UInt32.from(0);
5868
- return maxTravelDistance(this);
5869
- }
5870
- get isIdle() {
5871
- return this.is_idle;
5872
- }
5873
- getFlightOrigin(flightTaskIndex) {
5874
- return Coordinates.from(getFlightOrigin(this, flightTaskIndex));
5875
- }
5876
- destinationLocation() {
5877
- const dest = getDestinationLocation(this);
5878
- return dest ? Coordinates.from(dest) : undefined;
5879
- }
5880
- positionAt(now) {
5881
- const taskIndex = this.sched.currentTaskIndex(now);
5882
- const progress = this.sched.currentTaskProgress(now);
5883
- return Coordinates.from(getPositionAt(this, taskIndex, progress));
5884
- }
5885
- isInFlight(now) {
5886
- return isInFlight(this, now);
5887
- }
5888
- isRecharging(now) {
5889
- return isRecharging(this, now);
5890
- }
5891
- isLoading(now) {
5892
- return isLoading(this, now);
5893
- }
5894
- isUnloading(now) {
5895
- return isUnloading(this, now);
5896
- }
5897
- isGathering(now) {
5898
- return isGathering(this, now);
5899
- }
5900
- get hasEngines() {
5901
- return this.engines !== undefined;
5902
- }
5903
- get hasGenerator() {
5904
- return this.generator !== undefined;
5905
- }
5906
- get hasGatherer() {
5907
- return this.gatherer !== undefined;
5908
- }
5909
- get hasWarp() {
5910
- return this.warp !== undefined;
5911
- }
5912
- project() {
5913
- return projectEntity(this);
5914
- }
5915
- projectAt(now) {
5916
- return projectEntityAt(this, now);
5917
- }
5918
- get location() {
5919
- return Location.from(this.coordinates);
5920
- }
5921
- get totalCargoMass() {
5922
- return this.inv.totalMass;
5923
- }
5924
- get totalMass() {
5925
- let mass = UInt64.from(this.hullmass ?? 0).adding(this.totalCargoMass);
5926
- if (this.loaders) {
5927
- mass = mass.adding(UInt64.from(this.loaders.mass).multiplying(this.loaders.quantity));
5928
- }
5929
- return mass;
5930
- }
5931
- get maxCapacity() {
5932
- return UInt64.from(this.capacity);
5933
- }
5934
- hasSpace(goodMass, quantity) {
5935
- return this.totalMass.adding(goodMass.multiplying(quantity)).lte(this.maxCapacity);
5936
- }
5937
- get availableCapacity() {
5938
- return this.totalMass.gte(this.maxCapacity)
5939
- ? UInt64.from(0)
5940
- : this.maxCapacity.subtracting(this.totalMass);
5941
- }
5942
- getCargoForItem(goodId) {
5943
- return this.inv.forItem(goodId);
5944
- }
5945
- get sellableCargo() {
5946
- return this.inv.sellable;
5947
- }
5948
- get hasSellableCargo() {
5949
- return this.inv.hasSellable;
5950
- }
5951
- get sellableGoodsCount() {
5952
- return this.inv.sellableCount;
5953
- }
5954
- get isFull() {
5955
- return this.totalMass.gte(this.maxCapacity);
5956
- }
5957
- get energyPercent() {
5958
- if (!this.generator || this.energy === undefined)
5959
- return 0;
5960
- return energyPercent(this);
5961
- }
5962
- get needsRecharge() {
5963
- if (!this.generator || this.energy === undefined)
5964
- return false;
5965
- return needsRecharge(this);
5966
- }
5967
- hasEnergyFor(distance) {
5968
- if (!this.engines || !this.generator || this.energy === undefined)
5969
- return false;
5970
- return hasEnergyForDistance(this, distance);
5971
- }
5972
- }
5973
-
5974
- class Warehouse extends Types.entity_info {
5975
- get name() {
5976
- return this.entity_name;
5977
- }
5978
- get inv() {
5979
- return (this._inv ?? (this._inv = new InventoryAccessor(this)));
5980
- }
5981
- get inventory() {
5982
- return this.inv.items;
5983
- }
5984
- get sched() {
5985
- return (this._sched ?? (this._sched = new ScheduleAccessor(this)));
5986
- }
5987
- get isIdle() {
5988
- return this.is_idle;
5989
- }
5990
- isLoading(now) {
5991
- return isLoading(this, now);
5992
- }
5993
- isUnloading(now) {
5994
- return isUnloading(this, now);
5995
- }
5996
- get location() {
5997
- return Location.from(this.coordinates);
5998
- }
5999
- get totalCargoMass() {
6000
- return this.inv.totalMass;
6001
- }
6002
- get maxCapacity() {
6003
- return UInt64.from(this.capacity);
6004
- }
6005
- get availableCapacity() {
6006
- const cargo = this.totalCargoMass;
6007
- return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo);
6008
- }
6009
- hasSpace(goodMass, quantity) {
6010
- return this.totalCargoMass.adding(goodMass.multiplying(quantity)).lte(this.maxCapacity);
6011
- }
6012
- get isFull() {
6013
- return this.totalCargoMass.gte(this.maxCapacity);
6014
- }
6015
- getCargoForItem(goodId) {
6016
- return this.inv.forItem(goodId);
6017
- }
6018
- get orbitalAltitude() {
6019
- return this.coordinates.z?.toNumber() || 0;
6020
- }
6021
- get totalMass() {
6022
- const hull = this.hullmass ? UInt64.from(this.hullmass) : UInt64.from(0);
6023
- return hull.adding(this.totalCargoMass);
6024
- }
6025
- }
6026
-
6027
- class Container extends Types.entity_info {
6028
- get name() {
6029
- return this.entity_name;
6030
- }
6031
- get sched() {
6032
- return (this._sched ?? (this._sched = new ScheduleAccessor(this)));
6033
- }
6034
- get isIdle() {
6035
- return this.is_idle;
6036
- }
6037
- isLoading(now) {
6038
- return isLoading(this, now);
6039
- }
6040
- isUnloading(now) {
6041
- return isUnloading(this, now);
6042
- }
6043
- get location() {
6044
- return Location.from(this.coordinates);
6045
- }
6046
- get totalMass() {
6047
- return UInt64.from(this.hullmass ?? 0).adding(this.cargomass);
6048
- }
6049
- get maxCapacity() {
6050
- return UInt64.from(this.capacity);
6051
- }
6052
- get availableCapacity() {
6053
- const cargo = UInt64.from(this.cargomass);
6054
- return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo);
6055
- }
6056
- hasSpace(additionalMass) {
6057
- return UInt64.from(this.cargomass).adding(additionalMass).lte(this.maxCapacity);
6058
- }
6059
- get isFull() {
6060
- return UInt64.from(this.cargomass).gte(this.maxCapacity);
6061
- }
6062
- get orbitalAltitude() {
6063
- return this.coordinates.z?.toNumber() || 0;
6064
- }
6065
- }
6066
- function computeContainerCapabilities(stats) {
6067
- const density = stats['density'] ?? 500;
6068
- const strength = stats['strength'] ?? 500;
6069
- const ductility = stats['ductility'] ?? 500;
6070
- const purity = stats['purity'] ?? 500;
6071
- const hullmass = 25000 + 75 * density;
6072
- const statSum = strength + ductility + purity;
6073
- const exponent = statSum / 2997;
6074
- const capacity = Math.floor(1000000 * Math.pow(10, exponent));
6075
- return { hullmass, capacity };
6076
- }
6077
- function computeContainerT2Capabilities(stats) {
6078
- const strength = stats['strength'] ?? 0;
6079
- const density = stats['density'] ?? 0;
6080
- const ductility = stats['ductility'] ?? 0;
6081
- const purity = stats['purity'] ?? 0;
6082
- const hullmass = 20000 + 50 * density;
6083
- const statSum = strength + ductility + purity;
6084
- const exponent = statSum / 2500;
6085
- const capacity = Math.floor(1500000 * Math.pow(10, exponent));
6086
- return { hullmass, capacity };
6087
- }
6088
-
6089
- class EntitiesManager extends BaseManager {
6090
- async getEntity(type, id) {
6091
- const result = await this.server.readonly('getentity', {
6092
- entity_type: Name.from(type),
6093
- entity_id: id,
6094
- });
6095
- const entityInfo = result;
6096
- return this.wrapEntity(entityInfo);
6097
- }
6098
- async getEntities(owner, type) {
6099
- const ownerName = this.resolveOwner(owner);
6100
- const result = await this.server.readonly('getentities', {
6101
- owner: ownerName,
6102
- entity_type: type ? Name.from(type) : null,
6103
- });
6104
- const entities = result;
6105
- return entities.map((entity) => this.wrapEntity(entity));
6106
- }
6107
- async getSummaries(owner, type) {
6108
- const ownerName = this.resolveOwner(owner);
6109
- const result = await this.server.readonly('getsummaries', {
6110
- owner: ownerName,
6111
- entity_type: type ? Name.from(type) : null,
6112
- });
6113
- return result;
6114
- }
6115
- async getShip(id) {
6116
- return (await this.getEntity('ship', id));
6117
- }
6118
- async getWarehouse(id) {
6119
- return (await this.getEntity('warehouse', id));
6120
- }
6121
- async getContainer(id) {
6122
- return (await this.getEntity('container', id));
6123
- }
6124
- async getShips(owner) {
6125
- return (await this.getEntities(owner, 'ship'));
6126
- }
6127
- async getWarehouses(owner) {
6128
- return (await this.getEntities(owner, 'warehouse'));
6129
- }
6130
- async getContainers(owner) {
6131
- return (await this.getEntities(owner, 'container'));
6132
- }
6133
- async getShipSummaries(owner) {
6134
- return this.getSummaries(owner, 'ship');
6135
- }
6136
- async getWarehouseSummaries(owner) {
6137
- return this.getSummaries(owner, 'warehouse');
6138
- }
6139
- async getContainerSummaries(owner) {
6140
- return this.getSummaries(owner, 'container');
6141
- }
6142
- wrapEntity(entity) {
6143
- if (entity.type.equals('ship')) {
6144
- return new Ship(entity);
6145
- }
6146
- else if (entity.type.equals('warehouse')) {
6147
- return new Warehouse(entity);
6148
- }
6149
- else {
6150
- return new Container(entity);
6151
- }
6152
- }
6153
- resolveOwner(owner) {
6154
- if (typeof owner === 'object' && owner !== null && 'owner' in owner) {
6155
- return owner.owner;
6156
- }
6157
- return Name.from(owner);
6158
- }
6159
- }
6160
-
6161
- class Player extends Types.player_row {
6162
- static fromState(state) {
6163
- const playerRow = Types.player_row.from({
6164
- owner: Name.from(state.owner),
6165
- });
6166
- return new Player(playerRow);
6167
- }
6168
- }
6169
-
6170
- class PlayersManager extends BaseManager {
6171
- async getPlayer(account) {
6172
- const playerRow = await this.server.table('player').get(Name.from(account));
6173
- if (!playerRow) {
6174
- return undefined;
6175
- }
6176
- return new Player(playerRow);
6177
- }
6178
- }
6179
-
6180
- class LocationsManager extends BaseManager {
6181
- async hasSystem(location) {
6182
- const game = await this.getGame();
6183
- return hasSystem(game.config.seed, location);
6184
- }
6185
- async findNearbyPlanets(origin, maxDistance = 20) {
6186
- const game = await this.getGame();
6187
- return findNearbyPlanets(game.config.seed, origin, maxDistance);
6188
- }
6189
- async getLocationEntity(id) {
6190
- const row = await this.server.table('location').get(UInt64.from(id));
6191
- return row ?? undefined;
6192
- }
6193
- async getLocationEntityAt(coords) {
6194
- const id = coordsToLocationId(coords);
6195
- return this.getLocationEntity(id);
6196
- }
6197
- async getAllLocationEntities() {
6198
- return this.server.table('location').all();
6199
- }
6200
- }
6201
-
6202
- class EpochsManager extends BaseManager {
6203
- async getCurrentHeight() {
6204
- const game = await this.getGame();
6205
- return getCurrentEpoch(game);
6206
- }
6207
- async getCurrent() {
6208
- const game = await this.getGame();
6209
- const epoch = await this.getCurrentHeight();
6210
- return getEpochInfo(game, epoch);
6211
- }
6212
- async getByHeight(height) {
6213
- const game = await this.getGame();
6214
- return getEpochInfo(game, UInt64.from(height));
6215
- }
6216
- async getTimeRemaining() {
6217
- const epochInfo = await this.getCurrent();
6218
- const now = Date.now();
6219
- const endTime = epochInfo.end.getTime();
6220
- return Math.max(0, endTime - now);
6221
- }
6222
- async getProgress() {
6223
- const epochInfo = await this.getCurrent();
6224
- const now = Date.now();
6225
- const startTime = epochInfo.start.getTime();
6226
- const endTime = epochInfo.end.getTime();
6227
- const duration = endTime - startTime;
6228
- const elapsed = now - startTime;
6229
- if (elapsed <= 0)
6230
- return 0;
6231
- if (elapsed >= duration)
6232
- return 1;
6233
- return elapsed / duration;
6234
- }
6235
- async fitsInCurrentEpoch(durationMs) {
6236
- const remaining = await this.getTimeRemaining();
6237
- return durationMs <= remaining;
6238
- }
6239
- }
6240
-
6241
- class ActionsManager extends BaseManager {
6242
- travel(shipId, destination, recharge = true) {
6243
- const x = Int64.from(destination.x);
6244
- const y = Int64.from(destination.y);
6245
- return this.server.action('travel', {
6246
- entity_type: EntityType.SHIP,
6247
- id: UInt64.from(shipId),
6248
- x,
6249
- y,
6250
- recharge,
6251
- });
6252
- }
6253
- grouptravel(entities, destination, recharge = true) {
6254
- const entityRefs = entities.map((e) => Types.entity_ref.from({
6255
- entity_type: e.entityType,
6256
- entity_id: UInt64.from(e.entityId),
6257
- }));
6258
- const x = Int64.from(destination.x);
6259
- const y = Int64.from(destination.y);
6260
- return this.server.action('grouptravel', {
6261
- entities: entityRefs,
6262
- x,
6263
- y,
6264
- recharge,
6265
- });
6266
- }
6267
- resolve(entityId, entityType = EntityType.SHIP) {
6268
- return this.server.action('resolve', {
6269
- entity_type: entityType,
6270
- id: UInt64.from(entityId),
6271
- });
6272
- }
6273
- cancel(entityId, count, entityType = EntityType.SHIP) {
6274
- return this.server.action('cancel', {
6275
- entity_type: entityType,
6276
- id: UInt64.from(entityId),
6277
- count: UInt64.from(count),
6278
- });
6279
- }
6280
- recharge(shipId) {
6281
- return this.server.action('recharge', {
6282
- entity_type: EntityType.SHIP,
6283
- id: UInt64.from(shipId),
6284
- });
6285
- }
6286
- transfer(sourceType, sourceId, destType, destId, goodId, quantity) {
6287
- return this.server.action('transfer', {
6288
- source_type: sourceType,
6289
- source_id: UInt64.from(sourceId),
6290
- dest_type: destType,
6291
- dest_id: UInt64.from(destId),
6292
- item_id: UInt16.from(goodId),
6293
- quantity: UInt32.from(quantity),
6294
- });
6295
- }
6296
- foundCompany(account, name) {
6297
- return this.platform.action('foundcompany', {
6298
- account: Name.from(account),
6299
- name,
6300
- });
6301
- }
6302
- join(account) {
6303
- return this.server.action('join', {
6304
- account: Name.from(account),
6305
- });
6306
- }
6307
- gather(shipId, stratum, quantity) {
6308
- return this.server.action('gather', {
6309
- entity_type: EntityType.SHIP,
6310
- id: UInt64.from(shipId),
6311
- stratum: UInt16.from(stratum),
6312
- quantity: UInt32.from(quantity),
6313
- });
6314
- }
6315
- warp(shipId, destination) {
6316
- const x = Int64.from(destination.x);
6317
- const y = Int64.from(destination.y);
6318
- return this.server.action('warp', {
6319
- entity_type: EntityType.SHIP,
6320
- id: UInt64.from(shipId),
6321
- x,
6322
- y,
6323
- });
6324
- }
6325
- craft(entityType, entityId, recipeId, quantity, inputs) {
6326
- const cargoInputs = inputs.map((i) => Types.cargo_item.from(i));
6327
- return this.server.action('craft', {
6328
- entity_type: entityType,
6329
- id: UInt64.from(entityId),
6330
- recipe_id: UInt16.from(recipeId),
6331
- quantity: UInt32.from(quantity),
6332
- inputs: cargoInputs,
6333
- });
6334
- }
6335
- blend(entityType, entityId, inputs) {
6336
- const cargoInputs = inputs.map((i) => Types.cargo_item.from(i));
6337
- return this.server.action('blend', {
6338
- entity_type: entityType,
6339
- id: UInt64.from(entityId),
6340
- inputs: cargoInputs,
6341
- });
6342
- }
6343
- deploy(entityType, entityId, packedItemId, seed, entityName) {
6344
- return this.server.action('deploy', {
6345
- entity_type: entityType,
6346
- id: UInt64.from(entityId),
6347
- packed_item_id: UInt16.from(packedItemId),
6348
- seed: UInt64.from(seed),
6349
- entity_name: entityName,
6350
- });
6351
- }
6352
- addmodule(entityType, entityId, moduleIndex, moduleCargoId, targetCargoId = UInt64.from(0)) {
6353
- return this.server.action('addmodule', {
6354
- entity_type: entityType,
6355
- entity_id: UInt64.from(entityId),
6356
- module_index: moduleIndex,
6357
- module_cargo_id: UInt64.from(moduleCargoId),
6358
- target_cargo_id: UInt64.from(targetCargoId),
6359
- });
6360
- }
6361
- rmmodule(entityType, entityId, moduleIndex, targetCargoId = UInt64.from(0)) {
6362
- return this.server.action('rmmodule', {
6363
- entity_type: entityType,
6364
- entity_id: UInt64.from(entityId),
6365
- module_index: moduleIndex,
6366
- target_cargo_id: UInt64.from(targetCargoId),
6367
- });
6368
- }
6369
- joinGame(account, companyName) {
6370
- return [this.foundCompany(account, companyName), this.join(account)];
6371
- }
6372
- }
6373
-
6374
- class GameContext {
6375
- constructor(client, server, platform) {
6376
- this.client = client;
6377
- this.server = server;
6378
- this.platform = platform;
6379
- }
6380
- get entities() {
6381
- if (!this._entities) {
6382
- this._entities = new EntitiesManager(this);
6383
- }
6384
- return this._entities;
6385
- }
6386
- get players() {
6387
- if (!this._players) {
6388
- this._players = new PlayersManager(this);
6389
- }
6390
- return this._players;
6391
- }
6392
- get locations() {
6393
- if (!this._locations) {
6394
- this._locations = new LocationsManager(this);
6395
- }
6396
- return this._locations;
6397
- }
6398
- get epochs() {
6399
- if (!this._epochs) {
6400
- this._epochs = new EpochsManager(this);
6401
- }
6402
- return this._epochs;
6403
- }
6404
- get actions() {
6405
- if (!this._actions) {
6406
- this._actions = new ActionsManager(this);
6407
- }
6408
- return this._actions;
6409
- }
6410
- async getGame(reload = false) {
6411
- if (!reload && this._gameCache) {
6412
- return this._gameCache;
6413
- }
6414
- const game = await this.platform.table('games').get();
6415
- if (!game) {
6416
- throw new Error('Game not initialized');
6417
- }
6418
- this._gameCache = game;
6419
- return game;
6420
- }
6421
- async getState(reload = false) {
6422
- if (!reload && this._stateCache) {
6423
- return this._stateCache;
6424
- }
6425
- const state = await this.server.table('state').get();
6426
- if (!state) {
6427
- throw new Error('Game state not initialized');
6428
- }
6429
- const game = this._gameCache;
6430
- this._stateCache = GameState.from(state, game);
6431
- return this._stateCache;
6432
- }
6433
- get cachedGame() {
6434
- return this._gameCache;
6435
- }
6436
- get cachedState() {
6437
- return this._stateCache;
6438
- }
6439
- }
6440
-
6441
- class Shipload {
6442
- constructor(chain, constructorOptions) {
6443
- const { client, platformContract, serverContract } = constructorOptions || {};
6444
- const apiClient = client || new APIClient({ url: chain.url });
6445
- const platform$1 = platformContract
6446
- ? platformContract
6447
- : new Contract$1({ client: apiClient });
6448
- const server$1 = serverContract
6449
- ? serverContract
6450
- : new Contract({ client: apiClient });
6451
- this._context = new GameContext(apiClient, server$1, platform$1);
6452
- }
6453
- static async load(chain, shiploadOptions) {
6454
- let platform$1 = new Contract$1({
6455
- client: new APIClient({ url: chain.url }),
6456
- });
6457
- if (shiploadOptions?.platformContractName) {
6458
- const client = shiploadOptions.client || new APIClient({ url: chain.url });
6459
- const contractKit = new ContractKit({ client });
6460
- platform$1 = await contractKit.load(shiploadOptions.platformContractName);
6461
- }
6462
- let server$1 = new Contract({
6463
- client: new APIClient({ url: chain.url }),
6464
- });
6465
- if (shiploadOptions?.serverContractName) {
6466
- const client = shiploadOptions.client || new APIClient({ url: chain.url });
6467
- const contractKit = new ContractKit({ client });
6468
- server$1 = await contractKit.load(shiploadOptions.serverContractName);
6469
- }
6470
- return new Shipload(chain, {
6471
- ...shiploadOptions,
6472
- platformContract: platform$1,
6473
- serverContract: server$1,
6474
- });
6475
- }
6476
- get client() {
6477
- return this._context.client;
6478
- }
6479
- get server() {
6480
- return this._context.server;
6481
- }
6482
- get platform() {
6483
- return this._context.platform;
6484
- }
6485
- get entities() {
6486
- return this._context.entities;
6487
- }
6488
- get players() {
6489
- return this._context.players;
6490
- }
6491
- get locations() {
6492
- return this._context.locations;
6493
- }
6494
- get epochs() {
6495
- return this._context.epochs;
6496
- }
6497
- get actions() {
6498
- return this._context.actions;
6499
- }
6500
- async getGame(reload = false) {
6501
- return this._context.getGame(reload);
6502
- }
6503
- async getState(reload = false) {
6504
- return this._context.getState(reload);
6505
- }
6506
- }
6507
-
6508
- function makeShip(state) {
6509
- const info = {
6510
- type: Name.from('ship'),
6511
- id: UInt64.from(state.id),
6512
- owner: Name.from(state.owner),
6513
- entity_name: state.name,
6514
- coordinates: Types.coordinates.from(state.coordinates),
6515
- cargomass: UInt32.from(0),
6516
- cargo: state.cargo || [],
6517
- is_idle: !state.schedule,
6518
- current_task_elapsed: UInt32.from(0),
6519
- current_task_remaining: UInt32.from(0),
6520
- pending_tasks: [],
6521
- };
6522
- if (state.hullmass !== undefined)
6523
- info.hullmass = UInt32.from(state.hullmass);
6524
- if (state.capacity !== undefined)
6525
- info.capacity = UInt32.from(state.capacity);
6526
- if (state.energy !== undefined)
6527
- info.energy = UInt16.from(state.energy);
6528
- if (state.engines)
6529
- info.engines = state.engines;
6530
- if (state.generator)
6531
- info.generator = state.generator;
6532
- if (state.loaders)
6533
- info.loaders = state.loaders;
6534
- if (state.schedule)
6535
- info.schedule = state.schedule;
6536
- const entityInfo = Types.entity_info.from(info);
6537
- return new Ship(entityInfo);
6538
- }
6539
- function makeWarehouse(state) {
6540
- const info = {
6541
- type: Name.from('warehouse'),
6542
- id: UInt64.from(state.id),
6543
- owner: Name.from(state.owner),
6544
- entity_name: state.name,
6545
- coordinates: Types.coordinates.from(state.coordinates),
6546
- capacity: UInt32.from(state.capacity),
6547
- cargomass: UInt32.from(0),
6548
- cargo: state.cargo || [],
6549
- is_idle: !state.schedule,
6550
- current_task_elapsed: UInt32.from(0),
6551
- current_task_remaining: UInt32.from(0),
6552
- pending_tasks: [],
6553
- };
6554
- if (state.hullmass !== undefined)
6555
- info.hullmass = UInt32.from(state.hullmass);
6556
- if (state.loaders)
6557
- info.loaders = state.loaders;
6558
- if (state.schedule)
6559
- info.schedule = state.schedule;
6560
- const entityInfo = Types.entity_info.from(info);
6561
- return new Warehouse(entityInfo);
6562
- }
6563
- function makeContainer(state) {
6564
- const entityInfo = Types.entity_info.from({
6565
- type: Name.from('container'),
6566
- id: UInt64.from(state.id),
6567
- owner: Name.from(state.owner),
6568
- entity_name: state.name,
6569
- coordinates: Types.coordinates.from(state.coordinates),
6570
- hullmass: UInt32.from(state.hullmass),
6571
- capacity: UInt32.from(state.capacity),
6572
- cargomass: UInt32.from(state.cargomass || 0),
6573
- cargo: [],
6574
- is_idle: !state.schedule,
6575
- current_task_elapsed: UInt32.from(0),
6576
- current_task_remaining: UInt32.from(0),
6577
- pending_tasks: [],
6578
- schedule: state.schedule,
6579
- });
6580
- return new Container(entityInfo);
6581
- }
6582
-
6583
- function deriveStratum(epochSeed, coords, stratum, locationType, subtype, _maxDepth) {
6584
- const seed = Checksum256.from(epochSeed);
6585
- const c = Coordinates.from(coords);
6586
- const input = `stratum-${c.x}-${c.y}-${stratum}`;
6587
- const hashResult = hash512(seed, input);
6588
- const bytes = hashResult.array;
6589
- const rawReserve = ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0;
6590
- let reserve = 0;
6591
- if (rawReserve <= YIELD_THRESHOLD) {
6592
- const baseReserve = (rawReserve % 333) + 1;
6593
- const scale = depthScaleFactor(stratum);
6594
- reserve = Math.floor(baseReserve * scale);
6595
- }
6596
- if (reserve === 0)
6597
- return { itemId: 0, seed: 0n, richness: 0, reserve: 0 };
6598
- const eligible = getEligibleResources(locationType, subtype, stratum);
6599
- if (eligible.length === 0)
6600
- return { itemId: 0, seed: 0n, richness: 0, reserve: 0 };
6601
- const resourceRoll = ((bytes[4] << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7]) >>> 0;
6602
- let totalWeight = 0;
6603
- for (const id of eligible) {
6604
- totalWeight += getResourceWeight(id, stratum);
6605
- }
6606
- let selectedItemId = eligible[0];
6607
- if (totalWeight > 0) {
6608
- const roll = resourceRoll % totalWeight;
6609
- let cumulative = 0;
6610
- for (const id of eligible) {
6611
- cumulative += getResourceWeight(id, stratum);
6612
- if (roll < cumulative) {
6613
- selectedItemId = id;
6614
- break;
6615
- }
6616
- }
6617
- }
6618
- const seedBigInt = (BigInt(bytes[8]) << 56n) |
6619
- (BigInt(bytes[9]) << 48n) |
6620
- (BigInt(bytes[10]) << 40n) |
6621
- (BigInt(bytes[11]) << 32n) |
6622
- (BigInt(bytes[12]) << 24n) |
6623
- (BigInt(bytes[13]) << 16n) |
6624
- (BigInt(bytes[14]) << 8n) |
6625
- BigInt(bytes[15]);
6626
- const rawRichness = (bytes[16] << 8) | bytes[17];
6627
- const normalized = rawRichness / 65535;
6628
- const baseRichness = Math.floor(normalized * normalized * 999) + 1;
6629
- let depthBonus = 0;
6630
- if (stratum > 1) {
6631
- depthBonus = (50 * Math.log(stratum)) / Math.log(65535);
6632
- }
6633
- const richness = Math.min(Math.floor(baseRichness + depthBonus), 1000);
6634
- return { itemId: selectedItemId, seed: seedBigInt, richness, reserve };
6635
- }
6636
- function deriveResourceStats(seed) {
6637
- const seedBytes = new Uint8Array(8);
6638
- for (let i = 0; i < 8; i++) {
6639
- seedBytes[i] = Number(seed & 0xffn);
6640
- seed >>= 8n;
6641
- }
6642
- const hashResult = Checksum256.hash(Bytes.from(seedBytes));
6643
- const hashBytes = hashResult.array;
6644
- const extractU32 = (offset) => (hashBytes[offset] * 0x1000000 +
6645
- (hashBytes[offset + 1] << 16) +
6646
- (hashBytes[offset + 2] << 8) +
6647
- hashBytes[offset + 3]) >>> 0;
6648
- const weibull = (raw) => {
6649
- const u = raw / 4294967296;
6650
- let x = 0.27 * Math.sqrt(-Math.log(1 - u));
6651
- if (x > 1)
6652
- x = 1;
6653
- let val = Math.floor(x * 999) + 1;
6654
- if (val > 999)
6655
- val = 999;
6656
- return val;
6657
- };
6658
- return {
6659
- stat1: weibull(extractU32(0)),
6660
- stat2: weibull(extractU32(4)),
6661
- stat3: weibull(extractU32(8)),
6662
- };
6663
- }
6664
-
6665
- const METAL_STATS = [
6666
- {
6667
- key: 'strength',
6668
- label: 'Strength',
6669
- abbreviation: 'STR',
6670
- purpose: 'Raw structural/mechanical force',
6671
- },
6672
- {
6673
- key: 'tolerance',
6674
- label: 'Tolerance',
6675
- abbreviation: 'TOL',
6676
- purpose: 'Ability to withstand heat, pressure, and stress extremes',
6677
- },
6678
- {
6679
- key: 'density',
6680
- label: 'Density',
6681
- abbreviation: 'DEN',
6682
- purpose: 'Mass per unit',
6683
- inverted: true,
6684
- },
6685
- ];
6686
- const PRECIOUS_STATS = [
6687
- {
6688
- key: 'conductivity',
6689
- label: 'Conductivity',
6690
- abbreviation: 'CON',
6691
- purpose: 'Efficiency of energy/signal transfer',
6692
- },
6693
- {
6694
- key: 'ductility',
6695
- label: 'Ductility',
6696
- abbreviation: 'DUC',
6697
- purpose: 'Ability to be worked into fine, precise shapes',
6698
- },
6699
- {
6700
- key: 'reflectivity',
6701
- label: 'Reflectivity',
6702
- abbreviation: 'REF',
6703
- purpose: 'Surface quality for heat management and precision optics',
6704
- },
6705
- ];
6706
- const GAS_STATS = [
6707
- {
6708
- key: 'volatility',
6709
- label: 'Volatility',
6710
- abbreviation: 'VOL',
6711
- purpose: 'Energy release potential for propulsion and force',
6712
- },
6713
- {
6714
- key: 'reactivity',
6715
- label: 'Reactivity',
6716
- abbreviation: 'REA',
6717
- purpose: 'Chemical interaction speed for processing and penetration',
6718
- },
6719
- {
6720
- key: 'thermal',
6721
- label: 'Thermal',
6722
- abbreviation: 'THM',
6723
- purpose: 'Heat capacity for thermal management',
6724
- },
6725
- ];
6726
- const MINERAL_STATS = [
6727
- {
6728
- key: 'resonance',
6729
- label: 'Resonance',
6730
- abbreviation: 'RES',
6731
- purpose: 'Energy field interaction — storage, focusing, projection',
6732
- },
6733
- {
6734
- key: 'hardness',
6735
- label: 'Hardness',
6736
- abbreviation: 'HRD',
6737
- purpose: 'Resistance to wear — cutting surfaces, penetration',
6738
- },
6739
- {
6740
- key: 'clarity',
6741
- label: 'Clarity',
6742
- abbreviation: 'CLR',
6743
- purpose: 'Crystalline perfection — precision optics',
6744
- },
6745
- ];
6746
- const ORGANIC_STATS = [
6747
- {
6748
- key: 'plasticity',
6749
- label: 'Plasticity',
6750
- abbreviation: 'PLA',
6751
- purpose: 'Ease of reshaping — speeds processing',
6752
- },
6753
- {
6754
- key: 'insulation',
6755
- label: 'Insulation',
6756
- abbreviation: 'INS',
6757
- purpose: 'Energy containment — reduces energy loss',
6758
- },
6759
- {
6760
- key: 'purity',
6761
- label: 'Purity',
6762
- abbreviation: 'PUR',
6763
- purpose: 'Biological cleanliness — better composites and lubricants',
6764
- },
6765
- ];
6766
- const STAT_MAP = {
6767
- metal: METAL_STATS,
6768
- precious: PRECIOUS_STATS,
6769
- gas: GAS_STATS,
6770
- mineral: MINERAL_STATS,
6771
- organic: ORGANIC_STATS,
6772
- };
6773
- function getStatDefinitions(category) {
6774
- return STAT_MAP[category];
6775
- }
6776
- function getStatName(category, index) {
6777
- return STAT_MAP[category][index];
6778
- }
6779
- function resolveStats(category, stats) {
6780
- return {
6781
- definitions: STAT_MAP[category],
6782
- values: [stats.stat1, stats.stat2, stats.stat3],
6783
- };
6784
- }
6785
-
6786
- const ITEM_ENGINE_T1 = 10100;
6787
- const ITEM_GENERATOR_T1 = 10101;
6788
- const ITEM_GATHERER_T1 = 10102;
6789
- const ITEM_LOADER_T1 = 10103;
6790
- const ITEM_MANUFACTURING_T1 = 10104;
6791
- const ITEM_STORAGE_T1 = 10105;
6792
- const ITEM_HAULER_T1 = 10106;
6793
- const MODULE_ANY = 0;
6794
- const MODULE_ENGINE = 1;
6795
- const MODULE_GENERATOR = 2;
6796
- const MODULE_GATHERER = 3;
6797
- const MODULE_LOADER = 4;
6798
- const MODULE_WARP = 5;
6799
- const MODULE_CRAFTER = 6;
6800
- const MODULE_LAUNCHER = 7;
6801
- const MODULE_STORAGE = 8;
6802
- const MODULE_HAULER = 9;
6803
- function moduleAccepts(slotType, moduleType) {
6804
- return slotType === MODULE_ANY || slotType === moduleType;
6805
- }
6806
- function getModuleCapabilityType(itemId) {
6807
- switch (itemId) {
6808
- case ITEM_ENGINE_T1:
6809
- return MODULE_ENGINE;
6810
- case ITEM_GENERATOR_T1:
6811
- return MODULE_GENERATOR;
6812
- case ITEM_GATHERER_T1:
6813
- return MODULE_GATHERER;
6814
- case ITEM_LOADER_T1:
6815
- return MODULE_LOADER;
6816
- case ITEM_MANUFACTURING_T1:
6817
- return MODULE_CRAFTER;
6818
- case ITEM_STORAGE_T1:
6819
- return MODULE_STORAGE;
6820
- case ITEM_HAULER_T1:
6821
- return MODULE_HAULER;
6822
- default:
6823
- return 0xff;
6824
- }
6825
- }
6826
- function isModuleItem(itemId) {
6827
- return getModuleCapabilityType(itemId) !== 0xff;
4948
+ function isModuleItem(itemId) {
4949
+ return getModuleCapabilityType(itemId) !== 0xff;
6828
4950
  }
6829
4951
 
6830
4952
  const ITEM_MATTER_CONDUIT = 10005;
@@ -7241,211 +5363,2320 @@ const moduleRecipes = [
7241
5363
  function getModuleRecipe(id) {
7242
5364
  return moduleRecipes.find((r) => r.id === id);
7243
5365
  }
7244
- function getModuleRecipeByItemId(itemId) {
7245
- return moduleRecipes.find((r) => r.itemId === itemId);
5366
+ function getModuleRecipeByItemId(itemId) {
5367
+ return moduleRecipes.find((r) => r.itemId === itemId);
5368
+ }
5369
+ function getComponentById(id) {
5370
+ return components.find((c) => c.id === id);
5371
+ }
5372
+ function getEntityRecipe(id) {
5373
+ return entityRecipes.find((r) => r.id === id);
5374
+ }
5375
+ function getEntityRecipeByItemId(itemId) {
5376
+ return entityRecipes.find((r) => r.packedItemId === itemId);
5377
+ }
5378
+ function getEntitySlotLayout(packedItemId) {
5379
+ const recipe = getEntityRecipeByItemId(packedItemId);
5380
+ return recipe?.moduleSlots ?? [];
5381
+ }
5382
+ function getAllCraftableItems() {
5383
+ const items = [];
5384
+ for (const comp of components) {
5385
+ items.push({
5386
+ type: 'component',
5387
+ id: comp.id,
5388
+ name: comp.name,
5389
+ description: comp.description,
5390
+ color: comp.color,
5391
+ });
5392
+ }
5393
+ for (const entity of entityRecipes) {
5394
+ items.push({
5395
+ type: 'entity',
5396
+ id: entity.id,
5397
+ name: entity.name,
5398
+ description: entity.description,
5399
+ color: entity.color,
5400
+ });
5401
+ }
5402
+ for (const mod of moduleRecipes) {
5403
+ items.push({
5404
+ type: 'module',
5405
+ id: mod.id,
5406
+ name: mod.name,
5407
+ description: mod.description,
5408
+ color: mod.color,
5409
+ });
5410
+ }
5411
+ return items;
5412
+ }
5413
+ function getComponentsForCategory(category) {
5414
+ return components.filter((c) => c.recipe.some((r) => r.category === category));
5415
+ }
5416
+ function getComponentsForStat(statKey) {
5417
+ return components.filter((c) => c.stats.some((s) => s.key === statKey));
5418
+ }
5419
+
5420
+ const METAL_STATS = [
5421
+ {
5422
+ key: 'strength',
5423
+ label: 'Strength',
5424
+ abbreviation: 'STR',
5425
+ purpose: 'Raw structural/mechanical force',
5426
+ },
5427
+ {
5428
+ key: 'tolerance',
5429
+ label: 'Tolerance',
5430
+ abbreviation: 'TOL',
5431
+ purpose: 'Ability to withstand heat, pressure, and stress extremes',
5432
+ },
5433
+ {
5434
+ key: 'density',
5435
+ label: 'Density',
5436
+ abbreviation: 'DEN',
5437
+ purpose: 'Mass per unit',
5438
+ inverted: true,
5439
+ },
5440
+ ];
5441
+ const PRECIOUS_STATS = [
5442
+ {
5443
+ key: 'conductivity',
5444
+ label: 'Conductivity',
5445
+ abbreviation: 'CON',
5446
+ purpose: 'Efficiency of energy/signal transfer',
5447
+ },
5448
+ {
5449
+ key: 'ductility',
5450
+ label: 'Ductility',
5451
+ abbreviation: 'DUC',
5452
+ purpose: 'Ability to be worked into fine, precise shapes',
5453
+ },
5454
+ {
5455
+ key: 'reflectivity',
5456
+ label: 'Reflectivity',
5457
+ abbreviation: 'REF',
5458
+ purpose: 'Surface quality for heat management and precision optics',
5459
+ },
5460
+ ];
5461
+ const GAS_STATS = [
5462
+ {
5463
+ key: 'volatility',
5464
+ label: 'Volatility',
5465
+ abbreviation: 'VOL',
5466
+ purpose: 'Energy release potential for propulsion and force',
5467
+ },
5468
+ {
5469
+ key: 'reactivity',
5470
+ label: 'Reactivity',
5471
+ abbreviation: 'REA',
5472
+ purpose: 'Chemical interaction speed for processing and penetration',
5473
+ },
5474
+ {
5475
+ key: 'thermal',
5476
+ label: 'Thermal',
5477
+ abbreviation: 'THM',
5478
+ purpose: 'Heat capacity for thermal management',
5479
+ },
5480
+ ];
5481
+ const MINERAL_STATS = [
5482
+ {
5483
+ key: 'resonance',
5484
+ label: 'Resonance',
5485
+ abbreviation: 'RES',
5486
+ purpose: 'Energy field interaction — storage, focusing, projection',
5487
+ },
5488
+ {
5489
+ key: 'hardness',
5490
+ label: 'Hardness',
5491
+ abbreviation: 'HRD',
5492
+ purpose: 'Resistance to wear — cutting surfaces, penetration',
5493
+ },
5494
+ {
5495
+ key: 'clarity',
5496
+ label: 'Clarity',
5497
+ abbreviation: 'CLR',
5498
+ purpose: 'Crystalline perfection — precision optics',
5499
+ },
5500
+ ];
5501
+ const ORGANIC_STATS = [
5502
+ {
5503
+ key: 'plasticity',
5504
+ label: 'Plasticity',
5505
+ abbreviation: 'PLA',
5506
+ purpose: 'Ease of reshaping — speeds processing',
5507
+ },
5508
+ {
5509
+ key: 'insulation',
5510
+ label: 'Insulation',
5511
+ abbreviation: 'INS',
5512
+ purpose: 'Energy containment — reduces energy loss',
5513
+ },
5514
+ {
5515
+ key: 'purity',
5516
+ label: 'Purity',
5517
+ abbreviation: 'PUR',
5518
+ purpose: 'Biological cleanliness — better composites and lubricants',
5519
+ },
5520
+ ];
5521
+ const STAT_MAP = {
5522
+ metal: METAL_STATS,
5523
+ precious: PRECIOUS_STATS,
5524
+ gas: GAS_STATS,
5525
+ mineral: MINERAL_STATS,
5526
+ organic: ORGANIC_STATS,
5527
+ };
5528
+ function getStatDefinitions(category) {
5529
+ return STAT_MAP[category];
5530
+ }
5531
+ function getStatName(category, index) {
5532
+ return STAT_MAP[category][index];
5533
+ }
5534
+ function resolveStats(category, stats) {
5535
+ return {
5536
+ definitions: STAT_MAP[category],
5537
+ values: [stats.stat1, stats.stat2, stats.stat3],
5538
+ };
5539
+ }
5540
+
5541
+ const RESERVE_TIERS = {
5542
+ small: { min: 15, max: 60 },
5543
+ medium: { min: 100, max: 200 },
5544
+ large: { min: 400, max: 700 },
5545
+ massive: { min: 1000, max: 2500 },
5546
+ motherlode: { min: 4000, max: 10000 },
5547
+ };
5548
+ const SHALLOW_THRESHOLDS = {
5549
+ small: 0.8,
5550
+ medium: 0.991946,
5551
+ large: 0.999946,
5552
+ massive: 0.999996,
5553
+ };
5554
+ const DEEP_THRESHOLDS = {
5555
+ small: 0.5,
5556
+ medium: 0.95892,
5557
+ large: 0.99892,
5558
+ massive: 0.99992,
5559
+ };
5560
+ const TIER_ROLL_MAX = 0x10000;
5561
+ function lerp$1(a, b, t) {
5562
+ return a + (b - a) * t;
5563
+ }
5564
+ function rollTier(tierRoll, stratum) {
5565
+ const d = Math.min(stratum, 65535) / 65535;
5566
+ const smallMax = lerp$1(SHALLOW_THRESHOLDS.small, DEEP_THRESHOLDS.small, d) * TIER_ROLL_MAX;
5567
+ const mediumMax = lerp$1(SHALLOW_THRESHOLDS.medium, DEEP_THRESHOLDS.medium, d) * TIER_ROLL_MAX;
5568
+ const largeMax = lerp$1(SHALLOW_THRESHOLDS.large, DEEP_THRESHOLDS.large, d) * TIER_ROLL_MAX;
5569
+ const massiveMax = lerp$1(SHALLOW_THRESHOLDS.massive, DEEP_THRESHOLDS.massive, d) * TIER_ROLL_MAX;
5570
+ if (tierRoll < smallMax)
5571
+ return 'small';
5572
+ if (tierRoll < mediumMax)
5573
+ return 'medium';
5574
+ if (tierRoll < largeMax)
5575
+ return 'large';
5576
+ if (tierRoll < massiveMax)
5577
+ return 'massive';
5578
+ return 'motherlode';
5579
+ }
5580
+ function rollWithinTier(withinRoll, range) {
5581
+ const u = withinRoll / 65535;
5582
+ const skewed = u * u;
5583
+ return Math.floor(range.min + skewed * (range.max - range.min));
5584
+ }
5585
+
5586
+ function deriveStratum(epochSeed, coords, stratum, locationType, subtype, _maxDepth) {
5587
+ const seed = Checksum256.from(epochSeed);
5588
+ const c = Coordinates.from(coords);
5589
+ const input = `stratum-${c.x}-${c.y}-${stratum}`;
5590
+ const hashResult = hash512(seed, input);
5591
+ const bytes = hashResult.array;
5592
+ const rawReserve = ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0;
5593
+ let reserve = 0;
5594
+ if (rawReserve <= YIELD_THRESHOLD) {
5595
+ const tierRoll = ((bytes[18] << 8) | bytes[19]) >>> 0;
5596
+ const withinRoll = ((bytes[20] << 8) | bytes[21]) >>> 0;
5597
+ const tier = rollTier(tierRoll, stratum);
5598
+ reserve = rollWithinTier(withinRoll, RESERVE_TIERS[tier]);
5599
+ }
5600
+ if (reserve === 0)
5601
+ return { itemId: 0, seed: 0n, richness: 0, reserve: 0 };
5602
+ const eligible = getEligibleResources(locationType, subtype, stratum);
5603
+ if (eligible.length === 0)
5604
+ return { itemId: 0, seed: 0n, richness: 0, reserve: 0 };
5605
+ const resourceRoll = ((bytes[4] << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7]) >>> 0;
5606
+ let totalWeight = 0;
5607
+ for (const id of eligible) {
5608
+ totalWeight += getResourceWeight(id, stratum);
5609
+ }
5610
+ let selectedItemId = eligible[0];
5611
+ if (totalWeight > 0) {
5612
+ const roll = resourceRoll % totalWeight;
5613
+ let cumulative = 0;
5614
+ for (const id of eligible) {
5615
+ cumulative += getResourceWeight(id, stratum);
5616
+ if (roll < cumulative) {
5617
+ selectedItemId = id;
5618
+ break;
5619
+ }
5620
+ }
5621
+ }
5622
+ const seedBigInt = (BigInt(bytes[8]) << 56n) |
5623
+ (BigInt(bytes[9]) << 48n) |
5624
+ (BigInt(bytes[10]) << 40n) |
5625
+ (BigInt(bytes[11]) << 32n) |
5626
+ (BigInt(bytes[12]) << 24n) |
5627
+ (BigInt(bytes[13]) << 16n) |
5628
+ (BigInt(bytes[14]) << 8n) |
5629
+ BigInt(bytes[15]);
5630
+ const rawRichness = (bytes[16] << 8) | bytes[17];
5631
+ const normalized = rawRichness / 65535;
5632
+ const baseRichness = Math.floor(normalized * normalized * 999) + 1;
5633
+ let depthBonus = 0;
5634
+ if (stratum > 1) {
5635
+ depthBonus = (50 * Math.log(stratum)) / Math.log(65535);
5636
+ }
5637
+ const richness = Math.min(Math.floor(baseRichness + depthBonus), 1000);
5638
+ return { itemId: selectedItemId, seed: seedBigInt, richness, reserve };
5639
+ }
5640
+ function deriveResourceStats(seed) {
5641
+ const seedBytes = new Uint8Array(8);
5642
+ for (let i = 0; i < 8; i++) {
5643
+ seedBytes[i] = Number(seed & 0xffn);
5644
+ seed >>= 8n;
5645
+ }
5646
+ const hashResult = Checksum256.hash(Bytes.from(seedBytes));
5647
+ const hashBytes = hashResult.array;
5648
+ const extractU32 = (offset) => (hashBytes[offset] * 0x1000000 +
5649
+ (hashBytes[offset + 1] << 16) +
5650
+ (hashBytes[offset + 2] << 8) +
5651
+ hashBytes[offset + 3]) >>>
5652
+ 0;
5653
+ const weibull = (raw) => {
5654
+ const u = raw / 4294967296;
5655
+ let x = 0.24 * Math.sqrt(-Math.log(1 - u));
5656
+ if (x > 1)
5657
+ x = 1;
5658
+ let val = Math.floor(x * 999) + 1;
5659
+ if (val > 999)
5660
+ val = 999;
5661
+ return val;
5662
+ };
5663
+ return {
5664
+ stat1: weibull(extractU32(0)),
5665
+ stat2: weibull(extractU32(4)),
5666
+ stat3: weibull(extractU32(8)),
5667
+ };
5668
+ }
5669
+
5670
+ function encodeStats(values) {
5671
+ let seed = 0n;
5672
+ for (let i = 0; i < values.length && i < 6; i++) {
5673
+ seed |= BigInt(values[i] & 0x3ff) << BigInt(i * 10);
5674
+ }
5675
+ return seed;
5676
+ }
5677
+ function decodeStat(seed, index) {
5678
+ return Number((seed >> BigInt(index * 10)) & 0x3ffn);
5679
+ }
5680
+ function decodeStats(seed, count) {
5681
+ const stats = [];
5682
+ for (let i = 0; i < count; i++) {
5683
+ stats.push(decodeStat(seed, i));
5684
+ }
5685
+ return stats;
5686
+ }
5687
+ function mapStatsToKeys(seed, statDefs) {
5688
+ const values = decodeStats(seed, statDefs.length);
5689
+ const result = {};
5690
+ for (let i = 0; i < statDefs.length; i++) {
5691
+ result[statDefs[i].key] = values[i];
5692
+ }
5693
+ return result;
5694
+ }
5695
+ function decodeCraftedItemStats(itemId, seed) {
5696
+ const comp = getComponentById(itemId);
5697
+ if (comp)
5698
+ return mapStatsToKeys(seed, comp.stats);
5699
+ const entityRecipe = entityRecipes.find((r) => r.packedItemId === itemId);
5700
+ if (entityRecipe)
5701
+ return mapStatsToKeys(seed, entityRecipe.stats);
5702
+ const moduleRecipe = moduleRecipes.find((r) => r.itemId === itemId);
5703
+ if (moduleRecipe)
5704
+ return mapStatsToKeys(seed, moduleRecipe.stats);
5705
+ return {};
5706
+ }
5707
+ function blendStacks(stacks, statKey) {
5708
+ let totalQty = 0;
5709
+ let weightedSum = 0;
5710
+ for (const stack of stacks) {
5711
+ const val = stack.stats[statKey] ?? 0;
5712
+ weightedSum += val * stack.quantity;
5713
+ totalQty += stack.quantity;
5714
+ }
5715
+ if (totalQty === 0)
5716
+ return 0;
5717
+ return Math.floor(weightedSum / totalQty);
5718
+ }
5719
+ function computeComponentStats(componentId, categoryStacks) {
5720
+ const comp = getComponentById(componentId);
5721
+ if (!comp)
5722
+ return [];
5723
+ return comp.stats.map((statDef) => {
5724
+ const matching = categoryStacks.find((cs) => cs.category === statDef.source);
5725
+ const value = matching ? blendStacks(matching.stacks, statDef.key) : 0;
5726
+ return { key: statDef.key, value: Math.max(1, Math.min(999, value)) };
5727
+ });
5728
+ }
5729
+ function blendComponentStacks(stacks) {
5730
+ if (stacks.length === 0)
5731
+ return {};
5732
+ const allKeys = new Set();
5733
+ for (const s of stacks) {
5734
+ for (const k of Object.keys(s.stats))
5735
+ allKeys.add(k);
5736
+ }
5737
+ const result = {};
5738
+ for (const key of allKeys) {
5739
+ result[key] = blendStacks(stacks.map((s) => ({ quantity: s.quantity, stats: s.stats })), key);
5740
+ }
5741
+ return result;
5742
+ }
5743
+ function computeEntityStats(entityRecipeId, componentStacks) {
5744
+ const recipe = getEntityRecipe(entityRecipeId) ?? getModuleRecipe(entityRecipeId);
5745
+ if (!recipe)
5746
+ return [];
5747
+ const blendedByComponent = {};
5748
+ for (const [compId, stacks] of Object.entries(componentStacks)) {
5749
+ blendedByComponent[Number(compId)] = blendComponentStacks(stacks);
5750
+ }
5751
+ return recipe.stats.map((stat) => {
5752
+ const blended = blendedByComponent[stat.sourceComponentId] ?? {};
5753
+ const value = blended[stat.sourceStatKey] ?? 0;
5754
+ return { key: stat.key, value: Math.max(1, Math.min(999, value)) };
5755
+ });
5756
+ }
5757
+ function decodeStackStats(itemId, seed) {
5758
+ if (itemId >= 10000) {
5759
+ return decodeCraftedItemStats(itemId, BigInt(seed.toString()));
5760
+ }
5761
+ const raw = deriveResourceStats(BigInt(seed.toString()));
5762
+ return { stat1: raw.stat1, stat2: raw.stat2, stat3: raw.stat3 };
5763
+ }
5764
+ const categoryItemMass = {
5765
+ metal: 30000,
5766
+ precious: 40000,
5767
+ gas: 15000,
5768
+ mineral: 22000,
5769
+ organic: 15000,
5770
+ };
5771
+ function computeInputMass(itemId, itemType) {
5772
+ if (itemType === 'component') {
5773
+ const comp = getComponentById(itemId);
5774
+ if (!comp)
5775
+ return 0;
5776
+ return comp.recipe.reduce((sum, input) => {
5777
+ const mass = input.category ? categoryItemMass[input.category] ?? 0 : 0;
5778
+ return sum + mass * input.quantity;
5779
+ }, 0);
5780
+ }
5781
+ if (itemType === 'module') {
5782
+ const mod = getModuleRecipe(itemId);
5783
+ if (!mod)
5784
+ return 0;
5785
+ return mod.recipe.reduce((sum, input) => {
5786
+ const comp = input.itemId ? getComponentById(input.itemId) : undefined;
5787
+ return sum + (comp?.mass ?? 0) * input.quantity;
5788
+ }, 0);
5789
+ }
5790
+ if (itemType === 'entity') {
5791
+ const ent = getEntityRecipe(itemId);
5792
+ if (!ent)
5793
+ return 0;
5794
+ return ent.recipe.reduce((sum, input) => {
5795
+ const comp = input.itemId ? getComponentById(input.itemId) : undefined;
5796
+ return sum + (comp?.mass ?? 0) * input.quantity;
5797
+ }, 0);
5798
+ }
5799
+ return 0;
5800
+ }
5801
+ function blendCrossGroup(sources) {
5802
+ let weightedSum = 0;
5803
+ let totalWeight = 0;
5804
+ for (const src of sources) {
5805
+ weightedSum += src.value * src.weight;
5806
+ totalWeight += src.weight;
5807
+ }
5808
+ if (totalWeight === 0)
5809
+ return 1;
5810
+ const result = Math.floor(weightedSum / totalWeight);
5811
+ return Math.max(1, Math.min(999, result));
5812
+ }
5813
+ function blendCargoStacks(itemId, stacks) {
5814
+ const decoded = stacks.map((s) => ({
5815
+ quantity: s.quantity,
5816
+ stats: decodeStackStats(itemId, s.seed),
5817
+ }));
5818
+ const allKeys = Object.keys(decoded[0]?.stats ?? {});
5819
+ const blended = allKeys.map((key) => Math.max(1, Math.min(999, blendStacks(decoded, key))));
5820
+ return UInt64.from(encodeStats(blended));
5821
+ }
5822
+ function decodeRawStackToCategoryStats(seed, category) {
5823
+ const raw = deriveResourceStats(seed);
5824
+ const defs = getStatDefinitions(category);
5825
+ const result = {};
5826
+ if (defs[0])
5827
+ result[defs[0].key] = raw.stat1;
5828
+ if (defs[1])
5829
+ result[defs[1].key] = raw.stat2;
5830
+ if (defs[2])
5831
+ result[defs[2].key] = raw.stat3;
5832
+ return result;
5833
+ }
5834
+ function computeCraftedOutputSeed(outputItemId, slotInputs) {
5835
+ var _a;
5836
+ const component = getComponentById(outputItemId);
5837
+ if (component) {
5838
+ const categoryStacks = [];
5839
+ for (const slot of slotInputs) {
5840
+ if (!slot.category)
5841
+ continue;
5842
+ const slotIsComponent = getComponentById(slot.itemId) !== undefined;
5843
+ const stacks = slot.stacks.map((s) => ({
5844
+ quantity: s.quantity,
5845
+ stats: slotIsComponent
5846
+ ? decodeCraftedItemStats(slot.itemId, s.seed)
5847
+ : decodeRawStackToCategoryStats(s.seed, slot.category),
5848
+ }));
5849
+ categoryStacks.push({ category: slot.category, stacks });
5850
+ }
5851
+ const stats = computeComponentStats(outputItemId, categoryStacks);
5852
+ const ordered = component.stats.map((statDef) => {
5853
+ const found = stats.find((s) => s.key === statDef.key);
5854
+ return found ? found.value : 0;
5855
+ });
5856
+ return UInt64.from(encodeStats(ordered));
5857
+ }
5858
+ const entityRecipe = getEntityRecipeByItemId(outputItemId);
5859
+ if (entityRecipe) {
5860
+ const componentStacks = {};
5861
+ for (const slot of slotInputs) {
5862
+ if (slot.category !== undefined) {
5863
+ throw new Error(`entity recipe ${entityRecipe.id} expects component inputs but slot itemId=${slot.itemId} has category=${slot.category}`);
5864
+ }
5865
+ const list = (componentStacks[_a = slot.itemId] ?? (componentStacks[_a] = []));
5866
+ for (const s of slot.stacks) {
5867
+ list.push({
5868
+ quantity: s.quantity,
5869
+ stats: decodeCraftedItemStats(slot.itemId, s.seed),
5870
+ });
5871
+ }
5872
+ }
5873
+ const stats = computeEntityStats(entityRecipe.id, componentStacks);
5874
+ const ordered = entityRecipe.stats.map((statDef) => {
5875
+ const found = stats.find((s) => s.key === statDef.key);
5876
+ return found ? found.value : 0;
5877
+ });
5878
+ return UInt64.from(encodeStats(ordered));
5879
+ }
5880
+ throw new Error(`computeCraftedOutputSeed: no recipe found for outputItemId=${outputItemId}`);
5881
+ }
5882
+
5883
+ const itemsById = new Map();
5884
+ const synthesizedCache = new Map();
5885
+ for (const g of itemsData) {
5886
+ const item = Item.from({
5887
+ id: g.id,
5888
+ name: g.name,
5889
+ description: g.description,
5890
+ mass: g.mass,
5891
+ category: g.category,
5892
+ tier: g.tier,
5893
+ color: g.color,
5894
+ });
5895
+ itemsById.set(item.id.toNumber(), item);
5896
+ }
5897
+ const itemIds = Array.from(itemsById.values(), (i) => i.id);
5898
+ function synthesizeItem(id, source) {
5899
+ return Item.from({
5900
+ id,
5901
+ name: source.name,
5902
+ description: source.description,
5903
+ mass: source.mass,
5904
+ category: 'metal',
5905
+ tier: 't1',
5906
+ color: source.color,
5907
+ });
5908
+ }
5909
+ function synthesizeFromRecipes(id) {
5910
+ const component = getComponentById(id);
5911
+ if (component)
5912
+ return synthesizeItem(id, component);
5913
+ const entityRecipe = getEntityRecipeByItemId(id);
5914
+ if (entityRecipe) {
5915
+ return synthesizeItem(id, {
5916
+ ...entityRecipe,
5917
+ mass: computeInputMass(entityRecipe.id, 'entity'),
5918
+ });
5919
+ }
5920
+ const moduleRecipe = getModuleRecipeByItemId(id);
5921
+ if (moduleRecipe) {
5922
+ return synthesizeItem(id, {
5923
+ ...moduleRecipe,
5924
+ mass: computeInputMass(moduleRecipe.id, 'module'),
5925
+ });
5926
+ }
5927
+ return undefined;
5928
+ }
5929
+ function getItem(itemId) {
5930
+ const id = UInt16.from(itemId).toNumber();
5931
+ const existing = itemsById.get(id) ?? synthesizedCache.get(id);
5932
+ if (existing)
5933
+ return existing;
5934
+ const synthesized = synthesizeFromRecipes(id);
5935
+ if (synthesized) {
5936
+ synthesizedCache.set(id, synthesized);
5937
+ return synthesized;
5938
+ }
5939
+ throw new Error(`Item with id ${id} not found`);
5940
+ }
5941
+ function getItems() {
5942
+ return Array.from(itemsById.values());
5943
+ }
5944
+
5945
+ function calc_orbital_altitude(mass) {
5946
+ if (mass <= BASE_ORBITAL_MASS) {
5947
+ return MIN_ORBITAL_ALTITUDE;
5948
+ }
5949
+ const ratio = mass / BASE_ORBITAL_MASS;
5950
+ const capRatio = 10.0;
5951
+ let scale = Math.log(ratio) / Math.log(capRatio);
5952
+ scale = Math.min(scale, 1.0);
5953
+ return MIN_ORBITAL_ALTITUDE + Math.floor((MAX_ORBITAL_ALTITUDE - MIN_ORBITAL_ALTITUDE) * scale);
5954
+ }
5955
+ function distanceBetweenCoordinates(origin, destination) {
5956
+ return distanceBetweenPoints(origin.x, origin.y, destination.x, destination.y);
5957
+ }
5958
+ function distanceBetweenPoints(x1, y1, x2, y2) {
5959
+ const x = Math.pow(x1 - x2, 2);
5960
+ const y = Math.pow(y1 - y2, 2);
5961
+ return UInt64.from(Math.sqrt(x + y) * PRECISION$1);
5962
+ }
5963
+ function lerp(origin, destination, time) {
5964
+ return {
5965
+ x: (1 - time) * Number(origin.x) + time * Number(destination.x),
5966
+ y: (1 - time) * Number(origin.y) + time * Number(destination.y),
5967
+ };
5968
+ }
5969
+ function rotation(origin, destination) {
5970
+ return Math.atan2(destination.y - origin.y, destination.x - origin.x) * (180 / Math.PI) + 90;
5971
+ }
5972
+ function findNearbyPlanets(seed, origin, maxDistance = 20 * PRECISION$1) {
5973
+ const nearbySystems = [];
5974
+ const max = UInt64.from(maxDistance / PRECISION$1);
5975
+ const xMin = Int64.from(origin.x).subtracting(max);
5976
+ const xMax = Int64.from(origin.x).adding(max);
5977
+ const yMin = Int64.from(origin.y).subtracting(max);
5978
+ const yMax = Int64.from(origin.y).adding(max);
5979
+ for (let x = Number(xMin); x <= Number(xMax); x++) {
5980
+ for (let y = Number(yMin); y <= Number(yMax); y++) {
5981
+ const samePlace = x === Number(origin.x) && y === Number(origin.y);
5982
+ if (!samePlace) {
5983
+ const distance = distanceBetweenPoints(origin.x, origin.y, x, y);
5984
+ if (Number(distance) <= Number(maxDistance)) {
5985
+ const system = hasSystem(seed, { x, y });
5986
+ if (system) {
5987
+ nearbySystems.push({ origin, destination: { x, y }, distance });
5988
+ }
5989
+ }
5990
+ }
5991
+ }
5992
+ }
5993
+ return nearbySystems;
5994
+ }
5995
+ function calc_rechargetime(capacity, energy, recharge) {
5996
+ const cap = UInt32.from(capacity);
5997
+ const eng = UInt32.from(energy);
5998
+ if (eng.gte(cap))
5999
+ return UInt32.zero;
6000
+ return cap.subtracting(eng).dividing(recharge);
6001
+ }
6002
+ function calc_ship_rechargetime(ship) {
6003
+ if (!ship.generator)
6004
+ return UInt32.from(0);
6005
+ return calc_rechargetime(ship.generator.capacity, ship.energy ?? UInt16.from(0), ship.generator.recharge);
6006
+ }
6007
+ function calc_flighttime(distance, acceleration) {
6008
+ return UInt32.from(2 * Math.sqrt(Number(distance) / acceleration));
6009
+ }
6010
+ function calc_loader_flighttime(ship, mass, altitude) {
6011
+ const z = altitude ?? ship.coordinates.z?.toNumber() ?? calc_orbital_altitude(Number(mass));
6012
+ return calc_flighttime(z, calc_loader_acceleration(ship, mass));
6013
+ }
6014
+ function calc_loader_acceleration(ship, mass) {
6015
+ const thrust = ship.loaders ? Number(ship.loaders.thrust) : 0;
6016
+ const loaderMass = ship.loaders ? Number(ship.loaders.mass) : 0;
6017
+ return calc_acceleration(thrust, Number(mass) + loaderMass);
6018
+ }
6019
+ function calc_ship_flighttime(ship, mass, distance) {
6020
+ const acceleration = calc_ship_acceleration(ship, mass);
6021
+ return calc_flighttime(distance, acceleration);
6022
+ }
6023
+ function calc_ship_acceleration(ship, mass) {
6024
+ const thrust = ship.engines ? Number(ship.engines.thrust) : 0;
6025
+ return calc_acceleration(thrust, Number(mass));
6026
+ }
6027
+ function calc_acceleration(thrust, mass) {
6028
+ return (thrust / mass) * PRECISION$1;
6029
+ }
6030
+ function calc_ship_mass(ship, cargos) {
6031
+ const mass = UInt64.from(0);
6032
+ mass.add(ship.hullmass);
6033
+ if (ship.loaders && ship.loaders.quantity.gt(UInt32.zero)) {
6034
+ mass.add(ship.loaders.mass.multiplying(ship.loaders.quantity));
6035
+ }
6036
+ for (const cargo of cargos) {
6037
+ mass.add(getItem(cargo.item_id).mass.multiplying(cargo.quantity));
6038
+ }
6039
+ return mass;
6040
+ }
6041
+ function calc_energyusage(distance, drain) {
6042
+ return UInt64.from(distance).dividing(PRECISION$1).multiplying(drain);
6043
+ }
6044
+ function calculateTransferTime(ship, cargos, quantities) {
6045
+ let mass = UInt64.from(0);
6046
+ for (const cargo of cargos) {
6047
+ const qty = quantities?.get(Number(cargo.item_id)) ?? 0;
6048
+ if (qty > 0) {
6049
+ const good_mass = getItem(cargo.item_id).mass;
6050
+ const cargo_mass = good_mass.multiplying(qty);
6051
+ mass = UInt64.from(mass).adding(cargo_mass);
6052
+ }
6053
+ }
6054
+ if (mass.equals(UInt64.zero)) {
6055
+ return UInt32.from(0);
6056
+ }
6057
+ if (!ship.loaders)
6058
+ return UInt32.from(0);
6059
+ mass = UInt64.from(mass).adding(ship.loaders.mass);
6060
+ const transfer_time = calc_loader_flighttime(ship, mass);
6061
+ return transfer_time.dividing(ship.loaders.quantity);
6062
+ }
6063
+ function calculateRefuelingTime(ship) {
6064
+ return calc_ship_rechargetime(ship);
6065
+ }
6066
+ function calculateFlightTime(ship, cargos, distance) {
6067
+ const mass = calc_ship_mass(ship, cargos);
6068
+ return calc_ship_flighttime(ship, mass, distance);
6069
+ }
6070
+ function calculateLoadTimeBreakdown(ship, cargos, loadQuantities, unloadQuantities) {
6071
+ let mass_unload = UInt64.from(0);
6072
+ let mass_load = UInt64.from(0);
6073
+ for (const cargo of cargos) {
6074
+ const goodId = Number(cargo.item_id);
6075
+ const loadQty = loadQuantities?.get(goodId) ?? 0;
6076
+ const unloadQty = unloadQuantities?.get(goodId) ?? 0;
6077
+ if (loadQty > 0 || unloadQty > 0) {
6078
+ const good = getItem(cargo.item_id);
6079
+ if (loadQty > 0) {
6080
+ const cargo_mass = good.mass.multiplying(loadQty);
6081
+ mass_load = UInt64.from(mass_load).adding(cargo_mass);
6082
+ }
6083
+ if (unloadQty > 0) {
6084
+ const cargo_mass = good.mass.multiplying(unloadQty);
6085
+ mass_unload = UInt64.from(mass_unload).adding(cargo_mass);
6086
+ }
6087
+ }
6088
+ }
6089
+ let unloadTime = 0;
6090
+ let loadTime = 0;
6091
+ if (mass_unload.gt(UInt64.zero) && ship.loaders) {
6092
+ const totalMass = UInt64.from(mass_unload).adding(ship.loaders.mass);
6093
+ unloadTime = Number(calc_loader_flighttime(ship, totalMass));
6094
+ }
6095
+ if (mass_load.gt(UInt64.zero) && ship.loaders) {
6096
+ const totalMass = UInt64.from(mass_load).adding(ship.loaders.mass);
6097
+ loadTime = Number(calc_loader_flighttime(ship, totalMass));
6098
+ }
6099
+ const numLoaders = ship.loaders ? Number(ship.loaders.quantity) : 0;
6100
+ const totalTime = numLoaders > 0 ? (unloadTime + loadTime) / numLoaders : 0;
6101
+ const unloadTimePerLoader = numLoaders > 0 ? unloadTime / numLoaders : 0;
6102
+ const loadTimePerLoader = numLoaders > 0 ? loadTime / numLoaders : 0;
6103
+ return {
6104
+ unloadTime: unloadTimePerLoader,
6105
+ loadTime: loadTimePerLoader,
6106
+ totalTime,
6107
+ unloadMass: Number(mass_unload),
6108
+ loadMass: Number(mass_load),
6109
+ };
6110
+ }
6111
+ function estimateTravelTime(ship, travelMass, distance, options = {}) {
6112
+ const { needsRecharge = false, loadMass, unloadMass } = options;
6113
+ const flightTime = calc_ship_flighttime(ship, UInt64.from(travelMass), UInt64.from(distance));
6114
+ const rechargeTime = needsRecharge ? calc_ship_rechargetime(ship) : UInt32.zero;
6115
+ let loadTime = UInt32.zero;
6116
+ let unloadTime = UInt32.zero;
6117
+ if (loadMass &&
6118
+ UInt32.from(loadMass).gt(UInt32.zero) &&
6119
+ ship.loaders &&
6120
+ ship.loaders.quantity.gt(UInt32.zero)) {
6121
+ const totalMass = UInt64.from(loadMass).adding(ship.loaders.mass);
6122
+ loadTime = calc_loader_flighttime(ship, totalMass).dividing(ship.loaders.quantity);
6123
+ }
6124
+ if (unloadMass &&
6125
+ UInt32.from(unloadMass).gt(UInt32.zero) &&
6126
+ ship.loaders &&
6127
+ ship.loaders.quantity.gt(UInt32.zero)) {
6128
+ const totalMass = UInt64.from(unloadMass).adding(ship.loaders.mass);
6129
+ unloadTime = calc_loader_flighttime(ship, totalMass).dividing(ship.loaders.quantity);
6130
+ }
6131
+ return {
6132
+ flightTime,
6133
+ rechargeTime,
6134
+ loadTime,
6135
+ unloadTime,
6136
+ total: flightTime.adding(rechargeTime).adding(loadTime).adding(unloadTime),
6137
+ };
6138
+ }
6139
+ function estimateDealTravelTime(ship, shipMass, distance, loadMass) {
6140
+ const needsRecharge = !hasEnergyForDistance$1(ship, distance);
6141
+ const estimate = estimateTravelTime(ship, shipMass, distance, {
6142
+ needsRecharge,
6143
+ loadMass,
6144
+ });
6145
+ return estimate.total;
6146
+ }
6147
+ function hasEnergyForDistance$1(ship, distance) {
6148
+ if (!ship.engines)
6149
+ return false;
6150
+ const energyNeeded = UInt64.from(distance).dividing(PRECISION$1).multiplying(ship.engines.drain);
6151
+ return UInt64.from(ship.energy ?? 0).gte(energyNeeded);
6152
+ }
6153
+ function getFlightOrigin(entity, flightTaskIndex) {
6154
+ if (!entity.schedule)
6155
+ return entity.coordinates;
6156
+ let origin = entity.coordinates;
6157
+ for (let i = 0; i < flightTaskIndex && i < entity.schedule.tasks.length; i++) {
6158
+ const task = entity.schedule.tasks[i];
6159
+ if (task.type.equals(TaskType.TRAVEL) && task.coordinates) {
6160
+ origin = task.coordinates;
6161
+ }
6162
+ }
6163
+ return origin;
6164
+ }
6165
+ function getDestinationLocation(entity) {
6166
+ if (!entity.schedule)
6167
+ return undefined;
6168
+ for (let i = entity.schedule.tasks.length - 1; i >= 0; i--) {
6169
+ const task = entity.schedule.tasks[i];
6170
+ if (task.type.equals(TaskType.TRAVEL) && task.coordinates) {
6171
+ return task.coordinates;
6172
+ }
6173
+ }
6174
+ return undefined;
6175
+ }
6176
+ function getPositionAt(entity, taskIndex, taskProgress) {
6177
+ if (!entity.schedule || entity.schedule.tasks.length === 0 || taskIndex < 0) {
6178
+ return entity.coordinates;
6179
+ }
6180
+ const task = entity.schedule.tasks[taskIndex];
6181
+ if (!task.type.equals(TaskType.TRAVEL) || !task.coordinates) {
6182
+ return getFlightOrigin(entity, taskIndex);
6183
+ }
6184
+ const origin = getFlightOrigin(entity, taskIndex);
6185
+ const destination = task.coordinates;
6186
+ const interpolated = lerp(origin, destination, taskProgress);
6187
+ return {
6188
+ x: Math.round(interpolated.x),
6189
+ y: Math.round(interpolated.y),
6190
+ };
6191
+ }
6192
+ function calc_transfer_duration(source, dest, cargoMass) {
6193
+ if (cargoMass === 0) {
6194
+ return 0;
6195
+ }
6196
+ let totalThrust = 0;
6197
+ let totalLoaderMass = 0;
6198
+ let totalQuantity = 0;
6199
+ if (source.loaders) {
6200
+ const thrust = typeof source.loaders.thrust === 'number'
6201
+ ? source.loaders.thrust
6202
+ : source.loaders.thrust.toNumber();
6203
+ const mass = typeof source.loaders.mass === 'number'
6204
+ ? source.loaders.mass
6205
+ : source.loaders.mass.toNumber();
6206
+ const qty = typeof source.loaders.quantity === 'number'
6207
+ ? source.loaders.quantity
6208
+ : source.loaders.quantity.toNumber();
6209
+ totalThrust += thrust * qty;
6210
+ totalLoaderMass += mass * qty;
6211
+ totalQuantity += qty;
6212
+ }
6213
+ if (dest.loaders) {
6214
+ const thrust = typeof dest.loaders.thrust === 'number'
6215
+ ? dest.loaders.thrust
6216
+ : dest.loaders.thrust.toNumber();
6217
+ const mass = typeof dest.loaders.mass === 'number' ? dest.loaders.mass : dest.loaders.mass.toNumber();
6218
+ const qty = typeof dest.loaders.quantity === 'number'
6219
+ ? dest.loaders.quantity
6220
+ : dest.loaders.quantity.toNumber();
6221
+ totalThrust += thrust * qty;
6222
+ totalLoaderMass += mass * qty;
6223
+ totalQuantity += qty;
6224
+ }
6225
+ if (totalThrust === 0 || totalQuantity === 0) {
6226
+ return 0;
6227
+ }
6228
+ const sourceZ = typeof source.location.z === 'number'
6229
+ ? source.location.z
6230
+ : source.location.z?.toNumber() ?? 0;
6231
+ const destZ = typeof dest.location.z === 'number' ? dest.location.z : dest.location.z?.toNumber() ?? 0;
6232
+ const distance = Math.abs(sourceZ - destZ);
6233
+ const totalMass = cargoMass + totalLoaderMass;
6234
+ const acceleration = calc_acceleration(totalThrust, totalMass);
6235
+ const flightTime = 2 * Math.sqrt(distance / acceleration);
6236
+ return Math.floor(flightTime / totalQuantity);
6237
+ }
6238
+
6239
+ function capsHasMovement(caps) {
6240
+ return caps.engines !== undefined && caps.generator !== undefined;
6241
+ }
6242
+ function capsHasStorage(caps) {
6243
+ return caps.capacity !== undefined;
6244
+ }
6245
+ function capsHasLoaders(caps) {
6246
+ return caps.loaders !== undefined;
6247
+ }
6248
+ function capsHasGatherer(caps) {
6249
+ return caps.gatherer !== undefined;
6250
+ }
6251
+ function capsHasMass(caps) {
6252
+ return caps.hullmass !== undefined;
6253
+ }
6254
+
6255
+ function calcCargoItemMass(item) {
6256
+ const itemDef = getItem(item.item_id);
6257
+ let mass = UInt64.from(itemDef.mass).multiplying(item.quantity);
6258
+ for (const mod of item.modules) {
6259
+ if (mod.installed) {
6260
+ const modDef = getItem(mod.installed.item_id);
6261
+ mass = mass.adding(modDef.mass);
6262
+ }
6263
+ }
6264
+ return mass;
6265
+ }
6266
+ function calcCargoMass(entity) {
6267
+ let mass = UInt64.from(0);
6268
+ for (const item of entity.cargo) {
6269
+ mass = mass.adding(calcCargoItemMass(item));
6270
+ }
6271
+ return mass;
6272
+ }
6273
+ function calcStacksMass(stacks) {
6274
+ let mass = UInt64.from(0);
6275
+ for (const s of stacks) {
6276
+ mass = mass.adding(calcCargoItemMass(s));
6277
+ }
6278
+ return mass;
6279
+ }
6280
+ function availableCapacity$1(entity) {
6281
+ const cargoMass = calcCargoMass(entity);
6282
+ return entity.capacity.gt(cargoMass)
6283
+ ? UInt64.from(entity.capacity).subtracting(cargoMass)
6284
+ : UInt64.from(0);
6285
+ }
6286
+ function availableCapacityFromMass(capacity, cargoMass) {
6287
+ const cap = UInt64.from(capacity);
6288
+ const mass = UInt64.from(cargoMass);
6289
+ return cap.gt(mass) ? cap.subtracting(mass) : UInt64.from(0);
6290
+ }
6291
+ function hasSpace$1(entity, goodMass, quantity) {
6292
+ const additional = goodMass.multiplying(quantity);
6293
+ return availableCapacity$1(entity).gte(additional);
6294
+ }
6295
+ function hasSpaceForMass(capacity, currentMass, additionalMass) {
6296
+ return UInt64.from(currentMass).adding(additionalMass).lte(capacity);
6297
+ }
6298
+ function isFull$1(entity) {
6299
+ return UInt64.from(entity.cargomass).gte(entity.capacity);
6300
+ }
6301
+ function isFullFromMass(capacity, cargoMass) {
6302
+ return UInt64.from(cargoMass).gte(capacity);
6303
+ }
6304
+ function cargoItemToStack(item) {
6305
+ return {
6306
+ item_id: UInt16.from(item.item_id),
6307
+ quantity: UInt32.from(item.quantity),
6308
+ seed: item.seed,
6309
+ modules: item.modules ?? [],
6310
+ };
6311
+ }
6312
+ function stackToCargoItem(stack) {
6313
+ return Types.cargo_item.from({
6314
+ item_id: stack.item_id,
6315
+ quantity: stack.quantity,
6316
+ seed: stack.seed,
6317
+ modules: stack.modules,
6318
+ });
6319
+ }
6320
+ function seedEquals(a, b) {
6321
+ if (!a && !b)
6322
+ return true;
6323
+ if (!a || !b)
6324
+ return false;
6325
+ return a.equals(b);
6326
+ }
6327
+ function stackIdentityEqual(a, b) {
6328
+ return a.item_id.equals(b.item_id) && seedEquals(a.seed, b.seed);
6329
+ }
6330
+ function stackKey(s) {
6331
+ const seedVal = s.seed ? s.seed.toString() : '0';
6332
+ return `${s.item_id.toNumber()}:${seedVal}`;
6333
+ }
6334
+ function stacksEqual(a, b) {
6335
+ return stackIdentityEqual(a, b) && a.quantity.equals(b.quantity);
6336
+ }
6337
+ function mergeStacks(stacks, add) {
6338
+ const idx = stacks.findIndex((s) => stackIdentityEqual(s, add));
6339
+ if (idx === -1) {
6340
+ return [...stacks, { ...add }];
6341
+ }
6342
+ const result = stacks.slice();
6343
+ result[idx] = {
6344
+ ...result[idx],
6345
+ quantity: UInt32.from(result[idx].quantity.adding(add.quantity)),
6346
+ };
6347
+ return result;
6348
+ }
6349
+ function removeFromStacks(stacks, remove) {
6350
+ const idx = stacks.findIndex((s) => stackIdentityEqual(s, remove));
6351
+ if (idx === -1) {
6352
+ throw new Error(INSUFFICIENT_ITEM_QUANTITY);
6353
+ }
6354
+ const target = stacks[idx];
6355
+ if (target.quantity.lt(remove.quantity)) {
6356
+ throw new Error(INSUFFICIENT_ITEM_QUANTITY);
6357
+ }
6358
+ const remaining = UInt32.from(target.quantity.subtracting(remove.quantity));
6359
+ if (remaining.equals(UInt32.from(0))) {
6360
+ return [...stacks.slice(0, idx), ...stacks.slice(idx + 1)];
6361
+ }
6362
+ const result = stacks.slice();
6363
+ result[idx] = { ...target, quantity: remaining };
6364
+ return result;
6365
+ }
6366
+
6367
+ function hasSchedule$1(entity) {
6368
+ return !!entity.schedule && entity.schedule.tasks.length > 0;
6369
+ }
6370
+ function isIdle(entity) {
6371
+ return !hasSchedule$1(entity);
6372
+ }
6373
+ function getTasks(entity) {
6374
+ return entity.schedule?.tasks || [];
6375
+ }
6376
+ function scheduleDuration(entity) {
6377
+ if (!entity.schedule)
6378
+ return 0;
6379
+ return entity.schedule.tasks.reduce((sum, task) => sum + task.duration.toNumber(), 0);
6380
+ }
6381
+ function scheduleElapsed(entity, now) {
6382
+ if (!entity.schedule)
6383
+ return 0;
6384
+ const started = entity.schedule.started.toDate();
6385
+ const elapsed = Math.floor((now.getTime() - started.getTime()) / 1000);
6386
+ return Math.max(0, elapsed);
6387
+ }
6388
+ function scheduleRemaining(entity, now) {
6389
+ if (!entity.schedule)
6390
+ return 0;
6391
+ const duration = scheduleDuration(entity);
6392
+ const elapsed = scheduleElapsed(entity, now);
6393
+ return Math.max(0, duration - elapsed);
6394
+ }
6395
+ function scheduleComplete(entity, now) {
6396
+ return hasSchedule$1(entity) && scheduleRemaining(entity, now) === 0;
6397
+ }
6398
+ function currentTaskIndex(entity, now) {
6399
+ if (!entity.schedule || entity.schedule.tasks.length === 0)
6400
+ return -1;
6401
+ const elapsed = scheduleElapsed(entity, now);
6402
+ let timeAccum = 0;
6403
+ for (let i = 0; i < entity.schedule.tasks.length; i++) {
6404
+ const taskDuration = entity.schedule.tasks[i].duration.toNumber();
6405
+ if (elapsed < timeAccum + taskDuration) {
6406
+ return i;
6407
+ }
6408
+ timeAccum += taskDuration;
6409
+ }
6410
+ return entity.schedule.tasks.length - 1;
6411
+ }
6412
+ function currentTask(entity, now) {
6413
+ const index = currentTaskIndex(entity, now);
6414
+ if (index < 0 || !entity.schedule)
6415
+ return undefined;
6416
+ return entity.schedule.tasks[index];
6417
+ }
6418
+ function currentTaskType(entity, now) {
6419
+ const task = currentTask(entity, now);
6420
+ if (!task)
6421
+ return undefined;
6422
+ return task.type.toNumber();
6423
+ }
6424
+ function getTaskStartTime(entity, index) {
6425
+ if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length)
6426
+ return 0;
6427
+ let timeAccum = 0;
6428
+ for (let i = 0; i < index; i++) {
6429
+ timeAccum += entity.schedule.tasks[i].duration.toNumber();
6430
+ }
6431
+ return timeAccum;
6432
+ }
6433
+ function getTaskElapsed(entity, index, now) {
6434
+ if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length)
6435
+ return 0;
6436
+ const elapsed = scheduleElapsed(entity, now);
6437
+ const taskStart = getTaskStartTime(entity, index);
6438
+ const taskDuration = entity.schedule.tasks[index].duration.toNumber();
6439
+ if (elapsed <= taskStart)
6440
+ return 0;
6441
+ const elapsedInTask = elapsed - taskStart;
6442
+ return Math.min(elapsedInTask, taskDuration);
6443
+ }
6444
+ function getTaskRemaining(entity, index, now) {
6445
+ if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length)
6446
+ return 0;
6447
+ const taskDuration = entity.schedule.tasks[index].duration.toNumber();
6448
+ const taskElapsed = getTaskElapsed(entity, index, now);
6449
+ return Math.max(0, taskDuration - taskElapsed);
6450
+ }
6451
+ function isTaskComplete(entity, index, now) {
6452
+ if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length)
6453
+ return false;
6454
+ const taskDuration = entity.schedule.tasks[index].duration.toNumber();
6455
+ const taskElapsed = getTaskElapsed(entity, index, now);
6456
+ return taskElapsed >= taskDuration;
6457
+ }
6458
+ function isTaskInProgress(entity, index, now) {
6459
+ if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length)
6460
+ return false;
6461
+ const taskElapsed = getTaskElapsed(entity, index, now);
6462
+ const taskDuration = entity.schedule.tasks[index].duration.toNumber();
6463
+ return taskElapsed > 0 && taskElapsed < taskDuration;
6464
+ }
6465
+ function currentTaskProgress(entity, now) {
6466
+ const task = currentTask(entity, now);
6467
+ if (!task)
6468
+ return 0;
6469
+ const index = currentTaskIndex(entity, now);
6470
+ const elapsed = getTaskElapsed(entity, index, now);
6471
+ const duration = task.duration.toNumber();
6472
+ if (duration === 0)
6473
+ return 1;
6474
+ return Math.min(1, elapsed / duration);
6475
+ }
6476
+ function scheduleProgress(entity, now) {
6477
+ const duration = scheduleDuration(entity);
6478
+ if (duration === 0)
6479
+ return hasSchedule$1(entity) ? 1 : 0;
6480
+ const elapsed = scheduleElapsed(entity, now);
6481
+ return Math.min(1, elapsed / duration);
6482
+ }
6483
+ function isTaskType(entity, taskType, now) {
6484
+ return currentTaskType(entity, now) === taskType;
6485
+ }
6486
+ function isInFlight(entity, now) {
6487
+ return isTaskType(entity, TaskType.TRAVEL, now);
6488
+ }
6489
+ function isRecharging(entity, now) {
6490
+ return isTaskType(entity, TaskType.RECHARGE, now);
6491
+ }
6492
+ function isLoading(entity, now) {
6493
+ return isTaskType(entity, TaskType.LOAD, now);
6494
+ }
6495
+ function isUnloading(entity, now) {
6496
+ return isTaskType(entity, TaskType.UNLOAD, now);
6497
+ }
6498
+ function isGathering(entity, now) {
6499
+ return isTaskType(entity, TaskType.GATHER, now);
6500
+ }
6501
+
6502
+ var schedule = /*#__PURE__*/Object.freeze({
6503
+ __proto__: null,
6504
+ hasSchedule: hasSchedule$1,
6505
+ isIdle: isIdle,
6506
+ getTasks: getTasks,
6507
+ scheduleDuration: scheduleDuration,
6508
+ scheduleElapsed: scheduleElapsed,
6509
+ scheduleRemaining: scheduleRemaining,
6510
+ scheduleComplete: scheduleComplete,
6511
+ currentTaskIndex: currentTaskIndex,
6512
+ currentTask: currentTask,
6513
+ currentTaskType: currentTaskType,
6514
+ getTaskStartTime: getTaskStartTime,
6515
+ getTaskElapsed: getTaskElapsed,
6516
+ getTaskRemaining: getTaskRemaining,
6517
+ isTaskComplete: isTaskComplete,
6518
+ isTaskInProgress: isTaskInProgress,
6519
+ currentTaskProgress: currentTaskProgress,
6520
+ scheduleProgress: scheduleProgress,
6521
+ isTaskType: isTaskType,
6522
+ isInFlight: isInFlight,
6523
+ isRecharging: isRecharging,
6524
+ isLoading: isLoading,
6525
+ isUnloading: isUnloading,
6526
+ isGathering: isGathering
6527
+ });
6528
+
6529
+ function getHullMass(entity) {
6530
+ return UInt32.from(entity.hullmass ?? 0);
6531
+ }
6532
+ function createProjectedEntity(entity) {
6533
+ const shipMass = getHullMass(entity);
6534
+ const loaders = entity.loaders;
6535
+ const engines = entity.engines;
6536
+ const generator = entity.generator;
6537
+ const hauler = entity.hauler;
6538
+ const capacity = entity.capacity;
6539
+ const cargo = entity.cargo.map(cargoItemToStack);
6540
+ const projected = {
6541
+ location: Coordinates.from(entity.coordinates),
6542
+ energy: UInt16.from(entity.energy ?? 0),
6543
+ cargo,
6544
+ shipMass,
6545
+ capacity: capacity ? UInt64.from(capacity) : undefined,
6546
+ engines,
6547
+ generator,
6548
+ hauler,
6549
+ loaders,
6550
+ get cargoMass() {
6551
+ return calcStacksMass(this.cargo);
6552
+ },
6553
+ get totalMass() {
6554
+ let mass = UInt64.from(this.shipMass).adding(this.cargoMass);
6555
+ if (this.loaders) {
6556
+ mass = mass.adding(this.loaders.mass.multiplying(this.loaders.quantity));
6557
+ }
6558
+ return mass;
6559
+ },
6560
+ hasMovement() {
6561
+ return capsHasMovement(this.capabilities());
6562
+ },
6563
+ hasStorage() {
6564
+ return capsHasStorage(this.capabilities());
6565
+ },
6566
+ hasLoaders() {
6567
+ return capsHasLoaders(this.capabilities());
6568
+ },
6569
+ capabilities() {
6570
+ return {
6571
+ hullmass: this.shipMass,
6572
+ capacity: this.capacity ? UInt32.from(this.capacity) : undefined,
6573
+ engines: this.engines,
6574
+ generator: this.generator,
6575
+ loaders: this.loaders,
6576
+ };
6577
+ },
6578
+ state() {
6579
+ return {
6580
+ owner: entity.owner ?? Name.from(''),
6581
+ location: Types.coordinates.from(this.location),
6582
+ energy: this.energy,
6583
+ cargomass: UInt32.from(this.cargoMass),
6584
+ cargo: this.cargo.map(stackToCargoItem),
6585
+ };
6586
+ },
6587
+ };
6588
+ return projected;
6589
+ }
6590
+ function applyRechargeTask(projected, _task, options) {
6591
+ if (!projected.generator)
6592
+ return;
6593
+ if (options.complete) {
6594
+ projected.energy = UInt16.from(projected.generator.capacity);
6595
+ }
6596
+ else if (options.progress !== undefined) {
6597
+ const capacity = Number(projected.generator.capacity);
6598
+ const currentEnergy = Number(projected.energy);
6599
+ const rechargeAmount = (capacity - currentEnergy) * options.progress;
6600
+ projected.energy = UInt16.from(Math.min(capacity, currentEnergy + rechargeAmount));
6601
+ }
6602
+ }
6603
+ function applyFlightTask(projected, task, options) {
6604
+ if (!task.coordinates || !projected.engines)
6605
+ return;
6606
+ const origin = projected.location;
6607
+ const destination = Coordinates.from(task.coordinates);
6608
+ const distance = distanceBetweenCoordinates(origin, task.coordinates);
6609
+ const energyUsage = distance.dividing(PRECISION$1).multiplying(projected.engines.drain);
6610
+ if (options.complete) {
6611
+ projected.energy = projected.energy.gt(energyUsage)
6612
+ ? UInt16.from(projected.energy.subtracting(energyUsage))
6613
+ : UInt16.from(0);
6614
+ projected.location = destination;
6615
+ }
6616
+ else if (options.progress !== undefined) {
6617
+ const interpolated = lerp(origin, destination, options.progress);
6618
+ projected.location = Coordinates.from({
6619
+ x: Math.round(interpolated.x),
6620
+ y: Math.round(interpolated.y),
6621
+ });
6622
+ const partialEnergy = UInt64.from(Math.floor(Number(energyUsage) * options.progress));
6623
+ projected.energy = projected.energy.gt(partialEnergy)
6624
+ ? UInt16.from(projected.energy.subtracting(partialEnergy))
6625
+ : UInt16.from(0);
6626
+ }
6627
+ }
6628
+ function addCargoItem(projected, item) {
6629
+ projected.cargo = mergeStacks(projected.cargo, cargoItemToStack(item));
6630
+ }
6631
+ function removeCargoItem(projected, item) {
6632
+ projected.cargo = removeFromStacks(projected.cargo, cargoItemToStack(item));
6633
+ }
6634
+ function applyAddCargoTask(projected, task) {
6635
+ for (const item of task.cargo) {
6636
+ addCargoItem(projected, item);
6637
+ }
6638
+ }
6639
+ function applyRemoveCargoTask(projected, task) {
6640
+ for (const item of task.cargo) {
6641
+ removeCargoItem(projected, item);
6642
+ }
6643
+ }
6644
+ function applyEnergyCost(projected, task) {
6645
+ if (!task.energy_cost)
6646
+ return;
6647
+ const energyCost = UInt16.from(task.energy_cost);
6648
+ projected.energy = projected.energy.gt(energyCost)
6649
+ ? UInt16.from(projected.energy.subtracting(energyCost))
6650
+ : UInt16.from(0);
6651
+ }
6652
+ function applyGatherTask(projected, task, options) {
6653
+ if (!options.complete)
6654
+ return;
6655
+ applyEnergyCost(projected, task);
6656
+ applyAddCargoTask(projected, task);
6657
+ }
6658
+ function applyCraftTask(projected, task) {
6659
+ applyEnergyCost(projected, task);
6660
+ if (task.cargo.length === 0)
6661
+ return;
6662
+ for (let i = 0; i < task.cargo.length - 1; i++) {
6663
+ removeCargoItem(projected, task.cargo[i]);
6664
+ }
6665
+ addCargoItem(projected, task.cargo[task.cargo.length - 1]);
6666
+ }
6667
+ function applyDeployTask(projected, task) {
6668
+ applyEnergyCost(projected, task);
6669
+ if (task.cargo.length > 0) {
6670
+ removeCargoItem(projected, task.cargo[0]);
6671
+ }
6672
+ }
6673
+ function applyTask(projected, task) {
6674
+ switch (task.type.toNumber()) {
6675
+ case TaskType.RECHARGE:
6676
+ applyRechargeTask(projected, task, { complete: true });
6677
+ break;
6678
+ case TaskType.TRAVEL:
6679
+ applyFlightTask(projected, task, { complete: true });
6680
+ break;
6681
+ case TaskType.LOAD:
6682
+ case TaskType.UNWRAP:
6683
+ applyAddCargoTask(projected, task);
6684
+ break;
6685
+ case TaskType.UNLOAD:
6686
+ case TaskType.WRAP:
6687
+ applyRemoveCargoTask(projected, task);
6688
+ break;
6689
+ case TaskType.GATHER:
6690
+ applyGatherTask(projected, task, { complete: true });
6691
+ break;
6692
+ case TaskType.CRAFT:
6693
+ applyCraftTask(projected, task);
6694
+ break;
6695
+ case TaskType.DEPLOY:
6696
+ applyDeployTask(projected, task);
6697
+ break;
6698
+ }
6699
+ }
6700
+ function projectEntity(entity, options) {
6701
+ const projected = createProjectedEntity(entity);
6702
+ if (!entity.schedule || entity.schedule.tasks.length === 0)
6703
+ return projected;
6704
+ const tasks = entity.schedule.tasks;
6705
+ const taskCount = options?.upToTaskIndex !== undefined
6706
+ ? Math.max(0, Math.min(options.upToTaskIndex, tasks.length))
6707
+ : tasks.length;
6708
+ for (let i = 0; i < taskCount; i++) {
6709
+ applyTask(projected, tasks[i]);
6710
+ }
6711
+ return projected;
6712
+ }
6713
+ function validateSchedule(entity) {
6714
+ if (!entity.schedule || entity.schedule.tasks.length === 0)
6715
+ return;
6716
+ const projected = createProjectedEntity(entity);
6717
+ for (const task of entity.schedule.tasks) {
6718
+ applyTask(projected, task);
6719
+ if (projected.capacity && projected.cargoMass.gt(projected.capacity)) {
6720
+ throw new Error(ENTITY_CAPACITY_EXCEEDED);
6721
+ }
6722
+ }
6723
+ }
6724
+ function projectEntityAt(entity, now) {
6725
+ const projected = createProjectedEntity(entity);
6726
+ if (!entity.schedule || entity.schedule.tasks.length === 0) {
6727
+ return projected;
6728
+ }
6729
+ for (let i = 0; i < entity.schedule.tasks.length; i++) {
6730
+ const task = entity.schedule.tasks[i];
6731
+ const taskComplete = isTaskComplete(entity, i, now);
6732
+ const taskInProgress = isTaskInProgress(entity, i, now);
6733
+ if (!taskComplete && !taskInProgress) {
6734
+ break;
6735
+ }
6736
+ const progress = taskInProgress
6737
+ ? getTaskElapsed(entity, i, now) / task.duration.toNumber()
6738
+ : undefined;
6739
+ switch (task.type.toNumber()) {
6740
+ case TaskType.RECHARGE:
6741
+ applyRechargeTask(projected, task, { complete: taskComplete, progress });
6742
+ break;
6743
+ case TaskType.TRAVEL:
6744
+ applyFlightTask(projected, task, { complete: taskComplete, progress });
6745
+ break;
6746
+ case TaskType.LOAD:
6747
+ case TaskType.UNWRAP:
6748
+ if (taskComplete)
6749
+ applyAddCargoTask(projected, task);
6750
+ break;
6751
+ case TaskType.UNLOAD:
6752
+ case TaskType.WRAP:
6753
+ if (taskComplete)
6754
+ applyRemoveCargoTask(projected, task);
6755
+ break;
6756
+ case TaskType.GATHER:
6757
+ if (taskComplete)
6758
+ applyGatherTask(projected, task, { complete: true });
6759
+ break;
6760
+ case TaskType.CRAFT:
6761
+ if (taskComplete)
6762
+ applyCraftTask(projected, task);
6763
+ break;
6764
+ case TaskType.DEPLOY:
6765
+ if (taskComplete)
6766
+ applyDeployTask(projected, task);
6767
+ break;
6768
+ }
6769
+ }
6770
+ return projected;
6771
+ }
6772
+
6773
+ class Location {
6774
+ constructor(coordinates) {
6775
+ this.coordinates = Coordinates.from(coordinates);
6776
+ }
6777
+ static from(coordinates) {
6778
+ return new Location(Coordinates.from(coordinates));
6779
+ }
6780
+ hasSystemAt(gameSeed) {
6781
+ const seed = Checksum256.from(gameSeed);
6782
+ if (this._hasSystem === undefined || !this._gameSeed?.equals(seed)) {
6783
+ this._gameSeed = seed;
6784
+ this._hasSystem = hasSystem(seed, this.coordinates);
6785
+ }
6786
+ return this._hasSystem;
6787
+ }
6788
+ getLocationTypeAt(gameSeed) {
6789
+ return getLocationType(gameSeed, this.coordinates);
6790
+ }
6791
+ isGatherableAt(gameSeed) {
6792
+ return isGatherableLocation(this.getLocationTypeAt(gameSeed));
6793
+ }
6794
+ findNearby(gameSeed, maxDistance = 20) {
6795
+ return findNearbyPlanets(Checksum256.from(gameSeed), this.coordinates, maxDistance);
6796
+ }
6797
+ equals(other) {
6798
+ const otherCoords = other instanceof Location ? other.coordinates : Coordinates.from(other);
6799
+ return this.coordinates.equals(otherCoords);
6800
+ }
6801
+ get epoch() {
6802
+ return this._epoch;
6803
+ }
6804
+ clearCache() {
6805
+ this._epoch = undefined;
6806
+ }
6807
+ }
6808
+ function toLocation(coords) {
6809
+ if (coords instanceof Location) {
6810
+ return coords;
6811
+ }
6812
+ return Location.from(coords);
6813
+ }
6814
+
6815
+ class ScheduleAccessor {
6816
+ constructor(entity) {
6817
+ this.entity = entity;
6818
+ }
6819
+ get hasSchedule() {
6820
+ return hasSchedule$1(this.entity);
6821
+ }
6822
+ get isIdle() {
6823
+ return isIdle(this.entity);
6824
+ }
6825
+ get tasks() {
6826
+ return getTasks(this.entity);
6827
+ }
6828
+ duration() {
6829
+ return scheduleDuration(this.entity);
6830
+ }
6831
+ elapsed(now) {
6832
+ return scheduleElapsed(this.entity, now);
6833
+ }
6834
+ remaining(now) {
6835
+ return scheduleRemaining(this.entity, now);
6836
+ }
6837
+ complete(now) {
6838
+ return scheduleComplete(this.entity, now);
6839
+ }
6840
+ currentTaskIndex(now) {
6841
+ return currentTaskIndex(this.entity, now);
6842
+ }
6843
+ currentTask(now) {
6844
+ return currentTask(this.entity, now);
6845
+ }
6846
+ currentTaskType(now) {
6847
+ return currentTaskType(this.entity, now);
6848
+ }
6849
+ taskStartTime(index) {
6850
+ return getTaskStartTime(this.entity, index);
6851
+ }
6852
+ taskElapsed(index, now) {
6853
+ return getTaskElapsed(this.entity, index, now);
6854
+ }
6855
+ taskRemaining(index, now) {
6856
+ return getTaskRemaining(this.entity, index, now);
6857
+ }
6858
+ taskComplete(index, now) {
6859
+ return isTaskComplete(this.entity, index, now);
6860
+ }
6861
+ taskInProgress(index, now) {
6862
+ return isTaskInProgress(this.entity, index, now);
6863
+ }
6864
+ currentTaskProgress(now) {
6865
+ return currentTaskProgress(this.entity, now);
6866
+ }
6867
+ progress(now) {
6868
+ return scheduleProgress(this.entity, now);
6869
+ }
6870
+ }
6871
+ function createScheduleAccessor(entity) {
6872
+ return new ScheduleAccessor(entity);
6873
+ }
6874
+
6875
+ class EntityInventory extends Types.cargo_item {
6876
+ get item() {
6877
+ if (!this._item) {
6878
+ this._item = getItem(this.item_id);
6879
+ }
6880
+ return this._item;
6881
+ }
6882
+ get good() {
6883
+ return this.item;
6884
+ }
6885
+ get name() {
6886
+ return this.item.name;
6887
+ }
6888
+ get unitMass() {
6889
+ return this.item.mass;
6890
+ }
6891
+ get totalMass() {
6892
+ return UInt64.from(this.unitMass).multiplying(this.quantity);
6893
+ }
6894
+ get hasCargo() {
6895
+ return UInt32.from(this.quantity).gt(UInt32.from(0));
6896
+ }
6897
+ get isEmpty() {
6898
+ return UInt32.from(this.quantity).equals(UInt32.from(0));
6899
+ }
6900
+ }
6901
+
6902
+ class InventoryAccessor {
6903
+ constructor(entity) {
6904
+ this.entity = entity;
6905
+ }
6906
+ get items() {
6907
+ if (!this._items) {
6908
+ this._items = this.entity.cargo.map((item) => new EntityInventory(item));
6909
+ }
6910
+ return this._items;
6911
+ }
6912
+ get totalMass() {
6913
+ return this.items.reduce((sum, c) => sum.adding(c.totalMass), UInt64.from(0));
6914
+ }
6915
+ forItem(goodId) {
6916
+ return this.items.find((c) => c.item_id.equals(goodId));
6917
+ }
6918
+ get sellable() {
6919
+ return this.items.filter((c) => c.hasCargo);
6920
+ }
6921
+ get hasSellable() {
6922
+ return this.items.some((c) => c.hasCargo);
6923
+ }
6924
+ get sellableCount() {
6925
+ return this.items.filter((c) => c.hasCargo).length;
6926
+ }
6927
+ }
6928
+ function createInventoryAccessor(entity) {
6929
+ return new InventoryAccessor(entity);
6930
+ }
6931
+
6932
+ function maxTravelDistance(entity) {
6933
+ return UInt32.from(entity.generator.capacity)
6934
+ .dividing(entity.engines.drain)
6935
+ .multiplying(PRECISION$1);
6936
+ }
6937
+ function calcEnergyUsage(entity, distance) {
6938
+ return distance.dividing(PRECISION$1).multiplying(entity.engines.drain);
6939
+ }
6940
+ function hasEnergyForDistance(entity, distance) {
6941
+ const usage = calcEnergyUsage(entity, distance);
6942
+ return UInt64.from(entity.energy).gte(usage);
6943
+ }
6944
+ function energyPercent(entity) {
6945
+ return (Number(entity.energy) / Number(entity.generator.capacity)) * 100;
6946
+ }
6947
+ function needsRecharge(entity) {
6948
+ return UInt64.from(entity.energy).lt(entity.generator.capacity);
6949
+ }
6950
+
6951
+ class Ship extends Types.entity_info {
6952
+ get name() {
6953
+ return this.entity_name;
6954
+ }
6955
+ get inv() {
6956
+ return (this._inv ?? (this._inv = new InventoryAccessor(this)));
6957
+ }
6958
+ get inventory() {
6959
+ return this.inv.items;
6960
+ }
6961
+ get sched() {
6962
+ return (this._sched ?? (this._sched = new ScheduleAccessor(this)));
6963
+ }
6964
+ get maxDistance() {
6965
+ if (!this.generator || !this.engines)
6966
+ return UInt32.from(0);
6967
+ return maxTravelDistance(this);
6968
+ }
6969
+ get isIdle() {
6970
+ return this.is_idle;
6971
+ }
6972
+ getFlightOrigin(flightTaskIndex) {
6973
+ return Coordinates.from(getFlightOrigin(this, flightTaskIndex));
6974
+ }
6975
+ destinationLocation() {
6976
+ const dest = getDestinationLocation(this);
6977
+ return dest ? Coordinates.from(dest) : undefined;
6978
+ }
6979
+ positionAt(now) {
6980
+ const taskIndex = this.sched.currentTaskIndex(now);
6981
+ const progress = this.sched.currentTaskProgress(now);
6982
+ return Coordinates.from(getPositionAt(this, taskIndex, progress));
6983
+ }
6984
+ isInFlight(now) {
6985
+ return isInFlight(this, now);
6986
+ }
6987
+ isRecharging(now) {
6988
+ return isRecharging(this, now);
6989
+ }
6990
+ isLoading(now) {
6991
+ return isLoading(this, now);
6992
+ }
6993
+ isUnloading(now) {
6994
+ return isUnloading(this, now);
6995
+ }
6996
+ isGathering(now) {
6997
+ return isGathering(this, now);
6998
+ }
6999
+ get hasEngines() {
7000
+ return this.engines !== undefined;
7001
+ }
7002
+ get hasGenerator() {
7003
+ return this.generator !== undefined;
7004
+ }
7005
+ get hasGatherer() {
7006
+ return this.gatherer !== undefined;
7007
+ }
7008
+ get hasWarp() {
7009
+ return this.warp !== undefined;
7010
+ }
7011
+ project() {
7012
+ return projectEntity(this);
7013
+ }
7014
+ projectAt(now) {
7015
+ return projectEntityAt(this, now);
7016
+ }
7017
+ get location() {
7018
+ return Location.from(this.coordinates);
7019
+ }
7020
+ get totalCargoMass() {
7021
+ return this.inv.totalMass;
7022
+ }
7023
+ get totalMass() {
7024
+ let mass = UInt64.from(this.hullmass ?? 0).adding(this.totalCargoMass);
7025
+ if (this.loaders) {
7026
+ mass = mass.adding(UInt64.from(this.loaders.mass).multiplying(this.loaders.quantity));
7027
+ }
7028
+ return mass;
7029
+ }
7030
+ get maxCapacity() {
7031
+ return UInt64.from(this.capacity);
7032
+ }
7033
+ hasSpace(goodMass, quantity) {
7034
+ return this.totalMass.adding(goodMass.multiplying(quantity)).lte(this.maxCapacity);
7035
+ }
7036
+ get availableCapacity() {
7037
+ return this.totalMass.gte(this.maxCapacity)
7038
+ ? UInt64.from(0)
7039
+ : this.maxCapacity.subtracting(this.totalMass);
7040
+ }
7041
+ getCargoForItem(goodId) {
7042
+ return this.inv.forItem(goodId);
7043
+ }
7044
+ get sellableCargo() {
7045
+ return this.inv.sellable;
7046
+ }
7047
+ get hasSellableCargo() {
7048
+ return this.inv.hasSellable;
7049
+ }
7050
+ get sellableGoodsCount() {
7051
+ return this.inv.sellableCount;
7052
+ }
7053
+ get isFull() {
7054
+ return this.totalMass.gte(this.maxCapacity);
7055
+ }
7056
+ get energyPercent() {
7057
+ if (!this.generator || this.energy === undefined)
7058
+ return 0;
7059
+ return energyPercent(this);
7060
+ }
7061
+ get needsRecharge() {
7062
+ if (!this.generator || this.energy === undefined)
7063
+ return false;
7064
+ return needsRecharge(this);
7065
+ }
7066
+ hasEnergyFor(distance) {
7067
+ if (!this.engines || !this.generator || this.energy === undefined)
7068
+ return false;
7069
+ return hasEnergyForDistance(this, distance);
7070
+ }
7071
+ }
7072
+
7073
+ class Warehouse extends Types.entity_info {
7074
+ get name() {
7075
+ return this.entity_name;
7076
+ }
7077
+ get inv() {
7078
+ return (this._inv ?? (this._inv = new InventoryAccessor(this)));
7079
+ }
7080
+ get inventory() {
7081
+ return this.inv.items;
7082
+ }
7083
+ get sched() {
7084
+ return (this._sched ?? (this._sched = new ScheduleAccessor(this)));
7085
+ }
7086
+ get isIdle() {
7087
+ return this.is_idle;
7088
+ }
7089
+ isLoading(now) {
7090
+ return isLoading(this, now);
7091
+ }
7092
+ isUnloading(now) {
7093
+ return isUnloading(this, now);
7094
+ }
7095
+ get location() {
7096
+ return Location.from(this.coordinates);
7097
+ }
7098
+ get totalCargoMass() {
7099
+ return this.inv.totalMass;
7100
+ }
7101
+ get maxCapacity() {
7102
+ return UInt64.from(this.capacity);
7103
+ }
7104
+ get availableCapacity() {
7105
+ const cargo = this.totalCargoMass;
7106
+ return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo);
7107
+ }
7108
+ hasSpace(goodMass, quantity) {
7109
+ return this.totalCargoMass.adding(goodMass.multiplying(quantity)).lte(this.maxCapacity);
7110
+ }
7111
+ get isFull() {
7112
+ return this.totalCargoMass.gte(this.maxCapacity);
7113
+ }
7114
+ getCargoForItem(goodId) {
7115
+ return this.inv.forItem(goodId);
7116
+ }
7117
+ get orbitalAltitude() {
7118
+ return this.coordinates.z?.toNumber() || 0;
7119
+ }
7120
+ get totalMass() {
7121
+ const hull = this.hullmass ? UInt64.from(this.hullmass) : UInt64.from(0);
7122
+ return hull.adding(this.totalCargoMass);
7123
+ }
7246
7124
  }
7247
- function getComponentById(id) {
7248
- return components.find((c) => c.id === id);
7125
+
7126
+ class Container extends Types.entity_info {
7127
+ get name() {
7128
+ return this.entity_name;
7129
+ }
7130
+ get sched() {
7131
+ return (this._sched ?? (this._sched = new ScheduleAccessor(this)));
7132
+ }
7133
+ get isIdle() {
7134
+ return this.is_idle;
7135
+ }
7136
+ isLoading(now) {
7137
+ return isLoading(this, now);
7138
+ }
7139
+ isUnloading(now) {
7140
+ return isUnloading(this, now);
7141
+ }
7142
+ get location() {
7143
+ return Location.from(this.coordinates);
7144
+ }
7145
+ get totalMass() {
7146
+ return UInt64.from(this.hullmass ?? 0).adding(this.cargomass);
7147
+ }
7148
+ get maxCapacity() {
7149
+ return UInt64.from(this.capacity);
7150
+ }
7151
+ get availableCapacity() {
7152
+ const cargo = UInt64.from(this.cargomass);
7153
+ return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo);
7154
+ }
7155
+ hasSpace(additionalMass) {
7156
+ return UInt64.from(this.cargomass).adding(additionalMass).lte(this.maxCapacity);
7157
+ }
7158
+ get isFull() {
7159
+ return UInt64.from(this.cargomass).gte(this.maxCapacity);
7160
+ }
7161
+ get orbitalAltitude() {
7162
+ return this.coordinates.z?.toNumber() || 0;
7163
+ }
7249
7164
  }
7250
- function getEntityRecipe(id) {
7251
- return entityRecipes.find((r) => r.id === id);
7165
+ function computeContainerCapabilities(stats) {
7166
+ const density = stats['density'] ?? 500;
7167
+ const strength = stats['strength'] ?? 500;
7168
+ const ductility = stats['ductility'] ?? 500;
7169
+ const purity = stats['purity'] ?? 500;
7170
+ const hullmass = 25000 + 75 * density;
7171
+ const statSum = strength + ductility + purity;
7172
+ const exponent = statSum / 2997;
7173
+ const capacity = Math.floor(1000000 * Math.pow(10, exponent));
7174
+ return { hullmass, capacity };
7252
7175
  }
7253
- function getEntityRecipeByItemId(itemId) {
7254
- return entityRecipes.find((r) => r.packedItemId === itemId);
7176
+ function computeContainerT2Capabilities(stats) {
7177
+ const strength = stats['strength'] ?? 0;
7178
+ const density = stats['density'] ?? 0;
7179
+ const ductility = stats['ductility'] ?? 0;
7180
+ const purity = stats['purity'] ?? 0;
7181
+ const hullmass = 20000 + 50 * density;
7182
+ const statSum = strength + ductility + purity;
7183
+ const exponent = statSum / 2500;
7184
+ const capacity = Math.floor(1500000 * Math.pow(10, exponent));
7185
+ return { hullmass, capacity };
7255
7186
  }
7256
- function getEntitySlotLayout(packedItemId) {
7257
- const recipe = getEntityRecipeByItemId(packedItemId);
7258
- return recipe?.moduleSlots ?? [];
7187
+
7188
+ class EntitiesManager extends BaseManager {
7189
+ async getEntity(type, id) {
7190
+ const result = await this.server.readonly('getentity', {
7191
+ entity_type: Name.from(type),
7192
+ entity_id: id,
7193
+ });
7194
+ const entityInfo = result;
7195
+ return this.wrapEntity(entityInfo);
7196
+ }
7197
+ async getEntities(owner, type) {
7198
+ const ownerName = this.resolveOwner(owner);
7199
+ const result = await this.server.readonly('getentities', {
7200
+ owner: ownerName,
7201
+ entity_type: type ? Name.from(type) : null,
7202
+ });
7203
+ const entities = result;
7204
+ return entities.map((entity) => this.wrapEntity(entity));
7205
+ }
7206
+ async getSummaries(owner, type) {
7207
+ const ownerName = this.resolveOwner(owner);
7208
+ const result = await this.server.readonly('getsummaries', {
7209
+ owner: ownerName,
7210
+ entity_type: type ? Name.from(type) : null,
7211
+ });
7212
+ return result;
7213
+ }
7214
+ async getShip(id) {
7215
+ return (await this.getEntity('ship', id));
7216
+ }
7217
+ async getWarehouse(id) {
7218
+ return (await this.getEntity('warehouse', id));
7219
+ }
7220
+ async getContainer(id) {
7221
+ return (await this.getEntity('container', id));
7222
+ }
7223
+ async getShips(owner) {
7224
+ return (await this.getEntities(owner, 'ship'));
7225
+ }
7226
+ async getWarehouses(owner) {
7227
+ return (await this.getEntities(owner, 'warehouse'));
7228
+ }
7229
+ async getContainers(owner) {
7230
+ return (await this.getEntities(owner, 'container'));
7231
+ }
7232
+ async getShipSummaries(owner) {
7233
+ return this.getSummaries(owner, 'ship');
7234
+ }
7235
+ async getWarehouseSummaries(owner) {
7236
+ return this.getSummaries(owner, 'warehouse');
7237
+ }
7238
+ async getContainerSummaries(owner) {
7239
+ return this.getSummaries(owner, 'container');
7240
+ }
7241
+ wrapEntity(entity) {
7242
+ if (entity.type.equals('ship')) {
7243
+ return new Ship(entity);
7244
+ }
7245
+ else if (entity.type.equals('warehouse')) {
7246
+ return new Warehouse(entity);
7247
+ }
7248
+ else {
7249
+ return new Container(entity);
7250
+ }
7251
+ }
7252
+ resolveOwner(owner) {
7253
+ if (typeof owner === 'object' && owner !== null && 'owner' in owner) {
7254
+ return owner.owner;
7255
+ }
7256
+ return Name.from(owner);
7257
+ }
7258
+ }
7259
+
7260
+ class Player extends Types.player_row {
7261
+ static fromState(state) {
7262
+ const playerRow = Types.player_row.from({
7263
+ owner: Name.from(state.owner),
7264
+ });
7265
+ return new Player(playerRow);
7266
+ }
7267
+ }
7268
+
7269
+ class PlayersManager extends BaseManager {
7270
+ async getPlayer(account) {
7271
+ const playerRow = await this.server.table('player').get(Name.from(account));
7272
+ if (!playerRow) {
7273
+ return undefined;
7274
+ }
7275
+ return new Player(playerRow);
7276
+ }
7277
+ }
7278
+
7279
+ class LocationsManager extends BaseManager {
7280
+ async hasSystem(location) {
7281
+ const game = await this.getGame();
7282
+ return hasSystem(game.config.seed, location);
7283
+ }
7284
+ async findNearbyPlanets(origin, maxDistance = 20) {
7285
+ const game = await this.getGame();
7286
+ return findNearbyPlanets(game.config.seed, origin, maxDistance);
7287
+ }
7288
+ async getLocationEntity(id) {
7289
+ const row = await this.server.table('location').get(UInt64.from(id));
7290
+ return row ?? undefined;
7291
+ }
7292
+ async getLocationEntityAt(coords) {
7293
+ const id = coordsToLocationId(coords);
7294
+ return this.getLocationEntity(id);
7295
+ }
7296
+ async getAllLocationEntities() {
7297
+ return this.server.table('location').all();
7298
+ }
7299
+ }
7300
+
7301
+ class EpochsManager extends BaseManager {
7302
+ async getCurrentHeight() {
7303
+ const game = await this.getGame();
7304
+ return getCurrentEpoch(game);
7305
+ }
7306
+ async getCurrent() {
7307
+ const game = await this.getGame();
7308
+ const epoch = await this.getCurrentHeight();
7309
+ return getEpochInfo(game, epoch);
7310
+ }
7311
+ async getByHeight(height) {
7312
+ const game = await this.getGame();
7313
+ return getEpochInfo(game, UInt64.from(height));
7314
+ }
7315
+ async getTimeRemaining() {
7316
+ const epochInfo = await this.getCurrent();
7317
+ const now = Date.now();
7318
+ const endTime = epochInfo.end.getTime();
7319
+ return Math.max(0, endTime - now);
7320
+ }
7321
+ async getProgress() {
7322
+ const epochInfo = await this.getCurrent();
7323
+ const now = Date.now();
7324
+ const startTime = epochInfo.start.getTime();
7325
+ const endTime = epochInfo.end.getTime();
7326
+ const duration = endTime - startTime;
7327
+ const elapsed = now - startTime;
7328
+ if (elapsed <= 0)
7329
+ return 0;
7330
+ if (elapsed >= duration)
7331
+ return 1;
7332
+ return elapsed / duration;
7333
+ }
7334
+ async fitsInCurrentEpoch(durationMs) {
7335
+ const remaining = await this.getTimeRemaining();
7336
+ return durationMs <= remaining;
7337
+ }
7259
7338
  }
7260
- function getAllCraftableItems() {
7261
- const items = [];
7262
- for (const comp of components) {
7263
- items.push({
7264
- type: 'component',
7265
- id: comp.id,
7266
- name: comp.name,
7267
- description: comp.description,
7268
- color: comp.color,
7339
+
7340
+ class ActionsManager extends BaseManager {
7341
+ travel(shipId, destination, recharge = true) {
7342
+ const x = Int64.from(destination.x);
7343
+ const y = Int64.from(destination.y);
7344
+ return this.server.action('travel', {
7345
+ entity_type: EntityType.SHIP,
7346
+ id: UInt64.from(shipId),
7347
+ x,
7348
+ y,
7349
+ recharge,
7269
7350
  });
7270
7351
  }
7271
- for (const entity of entityRecipes) {
7272
- items.push({
7273
- type: 'entity',
7274
- id: entity.id,
7275
- name: entity.name,
7276
- description: entity.description,
7277
- color: entity.color,
7352
+ grouptravel(entities, destination, recharge = true) {
7353
+ const entityRefs = entities.map((e) => Types.entity_ref.from({
7354
+ entity_type: e.entityType,
7355
+ entity_id: UInt64.from(e.entityId),
7356
+ }));
7357
+ const x = Int64.from(destination.x);
7358
+ const y = Int64.from(destination.y);
7359
+ return this.server.action('grouptravel', {
7360
+ entities: entityRefs,
7361
+ x,
7362
+ y,
7363
+ recharge,
7278
7364
  });
7279
7365
  }
7280
- for (const mod of moduleRecipes) {
7281
- items.push({
7282
- type: 'module',
7283
- id: mod.id,
7284
- name: mod.name,
7285
- description: mod.description,
7286
- color: mod.color,
7366
+ resolve(entityId, entityType = EntityType.SHIP) {
7367
+ return this.server.action('resolve', {
7368
+ entity_type: entityType,
7369
+ id: UInt64.from(entityId),
7370
+ });
7371
+ }
7372
+ cancel(entityId, count, entityType = EntityType.SHIP) {
7373
+ return this.server.action('cancel', {
7374
+ entity_type: entityType,
7375
+ id: UInt64.from(entityId),
7376
+ count: UInt64.from(count),
7377
+ });
7378
+ }
7379
+ recharge(shipId) {
7380
+ return this.server.action('recharge', {
7381
+ entity_type: EntityType.SHIP,
7382
+ id: UInt64.from(shipId),
7383
+ });
7384
+ }
7385
+ transfer(sourceType, sourceId, destType, destId, goodId, quantity) {
7386
+ return this.server.action('transfer', {
7387
+ source_type: sourceType,
7388
+ source_id: UInt64.from(sourceId),
7389
+ dest_type: destType,
7390
+ dest_id: UInt64.from(destId),
7391
+ item_id: UInt16.from(goodId),
7392
+ quantity: UInt32.from(quantity),
7393
+ });
7394
+ }
7395
+ foundCompany(account, name) {
7396
+ return this.platform.action('foundcompany', {
7397
+ account: Name.from(account),
7398
+ name,
7399
+ });
7400
+ }
7401
+ join(account) {
7402
+ return this.server.action('join', {
7403
+ account: Name.from(account),
7404
+ });
7405
+ }
7406
+ gather(shipId, stratum, quantity) {
7407
+ return this.server.action('gather', {
7408
+ entity_type: EntityType.SHIP,
7409
+ id: UInt64.from(shipId),
7410
+ stratum: UInt16.from(stratum),
7411
+ quantity: UInt32.from(quantity),
7412
+ });
7413
+ }
7414
+ warp(shipId, destination) {
7415
+ const x = Int64.from(destination.x);
7416
+ const y = Int64.from(destination.y);
7417
+ return this.server.action('warp', {
7418
+ entity_type: EntityType.SHIP,
7419
+ id: UInt64.from(shipId),
7420
+ x,
7421
+ y,
7422
+ });
7423
+ }
7424
+ craft(entityType, entityId, recipeId, quantity, inputs) {
7425
+ const cargoInputs = inputs.map((i) => Types.cargo_item.from(i));
7426
+ return this.server.action('craft', {
7427
+ entity_type: entityType,
7428
+ id: UInt64.from(entityId),
7429
+ recipe_id: UInt16.from(recipeId),
7430
+ quantity: UInt32.from(quantity),
7431
+ inputs: cargoInputs,
7432
+ });
7433
+ }
7434
+ blend(entityType, entityId, inputs) {
7435
+ const cargoInputs = inputs.map((i) => Types.cargo_item.from(i));
7436
+ return this.server.action('blend', {
7437
+ entity_type: entityType,
7438
+ id: UInt64.from(entityId),
7439
+ inputs: cargoInputs,
7440
+ });
7441
+ }
7442
+ deploy(entityType, entityId, packedItemId, seed, entityName) {
7443
+ return this.server.action('deploy', {
7444
+ entity_type: entityType,
7445
+ id: UInt64.from(entityId),
7446
+ packed_item_id: UInt16.from(packedItemId),
7447
+ seed: UInt64.from(seed),
7448
+ entity_name: entityName,
7449
+ });
7450
+ }
7451
+ addmodule(entityType, entityId, moduleIndex, moduleCargoId, targetCargoId = UInt64.from(0)) {
7452
+ return this.server.action('addmodule', {
7453
+ entity_type: entityType,
7454
+ entity_id: UInt64.from(entityId),
7455
+ module_index: moduleIndex,
7456
+ module_cargo_id: UInt64.from(moduleCargoId),
7457
+ target_cargo_id: UInt64.from(targetCargoId),
7458
+ });
7459
+ }
7460
+ rmmodule(entityType, entityId, moduleIndex, targetCargoId = UInt64.from(0)) {
7461
+ return this.server.action('rmmodule', {
7462
+ entity_type: entityType,
7463
+ entity_id: UInt64.from(entityId),
7464
+ module_index: moduleIndex,
7465
+ target_cargo_id: UInt64.from(targetCargoId),
7466
+ });
7467
+ }
7468
+ joinGame(account, companyName) {
7469
+ return [this.foundCompany(account, companyName), this.join(account)];
7470
+ }
7471
+ }
7472
+
7473
+ class GameContext {
7474
+ constructor(client, server, platform) {
7475
+ this.client = client;
7476
+ this.server = server;
7477
+ this.platform = platform;
7478
+ }
7479
+ get entities() {
7480
+ if (!this._entities) {
7481
+ this._entities = new EntitiesManager(this);
7482
+ }
7483
+ return this._entities;
7484
+ }
7485
+ get players() {
7486
+ if (!this._players) {
7487
+ this._players = new PlayersManager(this);
7488
+ }
7489
+ return this._players;
7490
+ }
7491
+ get locations() {
7492
+ if (!this._locations) {
7493
+ this._locations = new LocationsManager(this);
7494
+ }
7495
+ return this._locations;
7496
+ }
7497
+ get epochs() {
7498
+ if (!this._epochs) {
7499
+ this._epochs = new EpochsManager(this);
7500
+ }
7501
+ return this._epochs;
7502
+ }
7503
+ get actions() {
7504
+ if (!this._actions) {
7505
+ this._actions = new ActionsManager(this);
7506
+ }
7507
+ return this._actions;
7508
+ }
7509
+ async getGame(reload = false) {
7510
+ if (!reload && this._gameCache) {
7511
+ return this._gameCache;
7512
+ }
7513
+ const game = await this.platform.table('games').get();
7514
+ if (!game) {
7515
+ throw new Error('Game not initialized');
7516
+ }
7517
+ this._gameCache = game;
7518
+ return game;
7519
+ }
7520
+ async getState(reload = false) {
7521
+ if (!reload && this._stateCache) {
7522
+ return this._stateCache;
7523
+ }
7524
+ const state = await this.server.table('state').get();
7525
+ if (!state) {
7526
+ throw new Error('Game state not initialized');
7527
+ }
7528
+ const game = this._gameCache;
7529
+ this._stateCache = GameState.from(state, game);
7530
+ return this._stateCache;
7531
+ }
7532
+ get cachedGame() {
7533
+ return this._gameCache;
7534
+ }
7535
+ get cachedState() {
7536
+ return this._stateCache;
7537
+ }
7538
+ }
7539
+
7540
+ class Shipload {
7541
+ constructor(chain, constructorOptions) {
7542
+ const { client, platformContract, serverContract } = constructorOptions || {};
7543
+ const apiClient = client || new APIClient({ url: chain.url });
7544
+ const platform$1 = platformContract
7545
+ ? platformContract
7546
+ : new Contract$1({ client: apiClient });
7547
+ const server$1 = serverContract
7548
+ ? serverContract
7549
+ : new Contract({ client: apiClient });
7550
+ this._context = new GameContext(apiClient, server$1, platform$1);
7551
+ }
7552
+ static async load(chain, shiploadOptions) {
7553
+ let platform$1 = new Contract$1({
7554
+ client: new APIClient({ url: chain.url }),
7555
+ });
7556
+ if (shiploadOptions?.platformContractName) {
7557
+ const client = shiploadOptions.client || new APIClient({ url: chain.url });
7558
+ const contractKit = new ContractKit({ client });
7559
+ platform$1 = await contractKit.load(shiploadOptions.platformContractName);
7560
+ }
7561
+ let server$1 = new Contract({
7562
+ client: new APIClient({ url: chain.url }),
7563
+ });
7564
+ if (shiploadOptions?.serverContractName) {
7565
+ const client = shiploadOptions.client || new APIClient({ url: chain.url });
7566
+ const contractKit = new ContractKit({ client });
7567
+ server$1 = await contractKit.load(shiploadOptions.serverContractName);
7568
+ }
7569
+ return new Shipload(chain, {
7570
+ ...shiploadOptions,
7571
+ platformContract: platform$1,
7572
+ serverContract: server$1,
7287
7573
  });
7288
7574
  }
7289
- return items;
7290
- }
7291
- function getComponentsForCategory(category) {
7292
- return components.filter((c) => c.recipe.some((r) => r.category === category));
7293
- }
7294
- function getComponentsForStat(statKey) {
7295
- return components.filter((c) => c.stats.some((s) => s.key === statKey));
7296
- }
7297
-
7298
- function encodeStats(values) {
7299
- let seed = 0n;
7300
- for (let i = 0; i < values.length && i < 6; i++) {
7301
- seed |= BigInt(values[i] & 0x3ff) << BigInt(i * 10);
7302
- }
7303
- return seed;
7304
- }
7305
- function decodeStat(seed, index) {
7306
- return Number((seed >> BigInt(index * 10)) & 0x3ffn);
7307
- }
7308
- function decodeStats(seed, count) {
7309
- const stats = [];
7310
- for (let i = 0; i < count; i++) {
7311
- stats.push(decodeStat(seed, i));
7575
+ get client() {
7576
+ return this._context.client;
7312
7577
  }
7313
- return stats;
7314
- }
7315
- function mapStatsToKeys(seed, statDefs) {
7316
- const values = decodeStats(seed, statDefs.length);
7317
- const result = {};
7318
- for (let i = 0; i < statDefs.length; i++) {
7319
- result[statDefs[i].key] = values[i];
7578
+ get server() {
7579
+ return this._context.server;
7320
7580
  }
7321
- return result;
7322
- }
7323
- function decodeCraftedItemStats(itemId, seed) {
7324
- const comp = getComponentById(itemId);
7325
- if (comp)
7326
- return mapStatsToKeys(seed, comp.stats);
7327
- const entityRecipe = entityRecipes.find((r) => r.packedItemId === itemId);
7328
- if (entityRecipe)
7329
- return mapStatsToKeys(seed, entityRecipe.stats);
7330
- const moduleRecipe = moduleRecipes.find((r) => r.itemId === itemId);
7331
- if (moduleRecipe)
7332
- return mapStatsToKeys(seed, moduleRecipe.stats);
7333
- return {};
7334
- }
7335
- function blendStacks(stacks, statKey) {
7336
- let totalQty = 0;
7337
- let weightedSum = 0;
7338
- for (const stack of stacks) {
7339
- const val = stack.stats[statKey] ?? 0;
7340
- weightedSum += val * stack.quantity;
7341
- totalQty += stack.quantity;
7581
+ get platform() {
7582
+ return this._context.platform;
7342
7583
  }
7343
- if (totalQty === 0)
7344
- return 0;
7345
- return Math.floor(weightedSum / totalQty);
7346
- }
7347
- function computeComponentStats(componentId, categoryStacks) {
7348
- const comp = getComponentById(componentId);
7349
- if (!comp)
7350
- return [];
7351
- return comp.stats.map((statDef) => {
7352
- const matching = categoryStacks.find((cs) => cs.category === statDef.source);
7353
- const value = matching ? blendStacks(matching.stacks, statDef.key) : 0;
7354
- return { key: statDef.key, value: Math.max(1, Math.min(999, value)) };
7355
- });
7356
- }
7357
- function blendComponentStacks(stacks) {
7358
- if (stacks.length === 0)
7359
- return {};
7360
- const allKeys = new Set();
7361
- for (const s of stacks) {
7362
- for (const k of Object.keys(s.stats))
7363
- allKeys.add(k);
7584
+ get entities() {
7585
+ return this._context.entities;
7364
7586
  }
7365
- const result = {};
7366
- for (const key of allKeys) {
7367
- result[key] = blendStacks(stacks.map((s) => ({ quantity: s.quantity, stats: s.stats })), key);
7587
+ get players() {
7588
+ return this._context.players;
7368
7589
  }
7369
- return result;
7370
- }
7371
- function computeEntityStats(entityRecipeId, componentStacks) {
7372
- const recipe = getEntityRecipe(entityRecipeId) ?? getModuleRecipe(entityRecipeId);
7373
- if (!recipe)
7374
- return [];
7375
- const blendedByComponent = {};
7376
- for (const [compId, stacks] of Object.entries(componentStacks)) {
7377
- blendedByComponent[Number(compId)] = blendComponentStacks(stacks);
7590
+ get locations() {
7591
+ return this._context.locations;
7378
7592
  }
7379
- return recipe.stats.map((stat) => {
7380
- const blended = blendedByComponent[stat.sourceComponentId] ?? {};
7381
- const value = blended[stat.sourceStatKey] ?? 0;
7382
- return { key: stat.key, value: Math.max(1, Math.min(999, value)) };
7383
- });
7384
- }
7385
- function decodeStackStats(itemId, seed) {
7386
- if (itemId >= 10000) {
7387
- return decodeCraftedItemStats(itemId, BigInt(seed.toString()));
7593
+ get epochs() {
7594
+ return this._context.epochs;
7388
7595
  }
7389
- const raw = deriveResourceStats(BigInt(seed.toString()));
7390
- return { stat1: raw.stat1, stat2: raw.stat2, stat3: raw.stat3 };
7391
- }
7392
- const categoryItemMass = {
7393
- metal: 30000,
7394
- precious: 40000,
7395
- gas: 15000,
7396
- mineral: 22000,
7397
- organic: 15000,
7398
- };
7399
- function computeInputMass(itemId, itemType) {
7400
- if (itemType === 'component') {
7401
- const comp = getComponentById(itemId);
7402
- if (!comp)
7403
- return 0;
7404
- return comp.recipe.reduce((sum, input) => {
7405
- const mass = input.category ? categoryItemMass[input.category] ?? 0 : 0;
7406
- return sum + mass * input.quantity;
7407
- }, 0);
7596
+ get actions() {
7597
+ return this._context.actions;
7408
7598
  }
7409
- if (itemType === 'module') {
7410
- const mod = getModuleRecipe(itemId);
7411
- if (!mod)
7412
- return 0;
7413
- return mod.recipe.reduce((sum, input) => {
7414
- const comp = input.itemId ? getComponentById(input.itemId) : undefined;
7415
- return sum + (comp?.mass ?? 0) * input.quantity;
7416
- }, 0);
7599
+ async getGame(reload = false) {
7600
+ return this._context.getGame(reload);
7417
7601
  }
7418
- if (itemType === 'entity') {
7419
- const ent = getEntityRecipe(itemId);
7420
- if (!ent)
7421
- return 0;
7422
- return ent.recipe.reduce((sum, input) => {
7423
- const comp = input.itemId ? getComponentById(input.itemId) : undefined;
7424
- return sum + (comp?.mass ?? 0) * input.quantity;
7425
- }, 0);
7602
+ async getState(reload = false) {
7603
+ return this._context.getState(reload);
7426
7604
  }
7427
- return 0;
7428
7605
  }
7429
- function blendCrossGroup(sources) {
7430
- let weightedSum = 0;
7431
- let totalWeight = 0;
7432
- for (const src of sources) {
7433
- weightedSum += src.value * src.weight;
7434
- totalWeight += src.weight;
7435
- }
7436
- if (totalWeight === 0)
7437
- return 1;
7438
- const result = Math.floor(weightedSum / totalWeight);
7439
- return Math.max(1, Math.min(999, result));
7606
+
7607
+ function makeShip(state) {
7608
+ const info = {
7609
+ type: Name.from('ship'),
7610
+ id: UInt64.from(state.id),
7611
+ owner: Name.from(state.owner),
7612
+ entity_name: state.name,
7613
+ coordinates: Types.coordinates.from(state.coordinates),
7614
+ cargomass: UInt32.from(0),
7615
+ cargo: state.cargo || [],
7616
+ is_idle: !state.schedule,
7617
+ current_task_elapsed: UInt32.from(0),
7618
+ current_task_remaining: UInt32.from(0),
7619
+ pending_tasks: [],
7620
+ };
7621
+ if (state.hullmass !== undefined)
7622
+ info.hullmass = UInt32.from(state.hullmass);
7623
+ if (state.capacity !== undefined)
7624
+ info.capacity = UInt32.from(state.capacity);
7625
+ if (state.energy !== undefined)
7626
+ info.energy = UInt16.from(state.energy);
7627
+ if (state.engines)
7628
+ info.engines = state.engines;
7629
+ if (state.generator)
7630
+ info.generator = state.generator;
7631
+ if (state.loaders)
7632
+ info.loaders = state.loaders;
7633
+ if (state.schedule)
7634
+ info.schedule = state.schedule;
7635
+ const entityInfo = Types.entity_info.from(info);
7636
+ return new Ship(entityInfo);
7440
7637
  }
7441
- function blendCargoStacks(itemId, stacks) {
7442
- const decoded = stacks.map((s) => ({
7443
- quantity: s.quantity,
7444
- stats: decodeStackStats(itemId, s.seed),
7445
- }));
7446
- const allKeys = Object.keys(decoded[0]?.stats ?? {});
7447
- const blended = allKeys.map((key) => Math.max(1, Math.min(999, blendStacks(decoded, key))));
7448
- return UInt64.from(encodeStats(blended));
7638
+ function makeWarehouse(state) {
7639
+ const info = {
7640
+ type: Name.from('warehouse'),
7641
+ id: UInt64.from(state.id),
7642
+ owner: Name.from(state.owner),
7643
+ entity_name: state.name,
7644
+ coordinates: Types.coordinates.from(state.coordinates),
7645
+ capacity: UInt32.from(state.capacity),
7646
+ cargomass: UInt32.from(0),
7647
+ cargo: state.cargo || [],
7648
+ is_idle: !state.schedule,
7649
+ current_task_elapsed: UInt32.from(0),
7650
+ current_task_remaining: UInt32.from(0),
7651
+ pending_tasks: [],
7652
+ };
7653
+ if (state.hullmass !== undefined)
7654
+ info.hullmass = UInt32.from(state.hullmass);
7655
+ if (state.loaders)
7656
+ info.loaders = state.loaders;
7657
+ if (state.schedule)
7658
+ info.schedule = state.schedule;
7659
+ const entityInfo = Types.entity_info.from(info);
7660
+ return new Warehouse(entityInfo);
7661
+ }
7662
+ function makeContainer(state) {
7663
+ const entityInfo = Types.entity_info.from({
7664
+ type: Name.from('container'),
7665
+ id: UInt64.from(state.id),
7666
+ owner: Name.from(state.owner),
7667
+ entity_name: state.name,
7668
+ coordinates: Types.coordinates.from(state.coordinates),
7669
+ hullmass: UInt32.from(state.hullmass),
7670
+ capacity: UInt32.from(state.capacity),
7671
+ cargomass: UInt32.from(state.cargomass || 0),
7672
+ cargo: [],
7673
+ is_idle: !state.schedule,
7674
+ current_task_elapsed: UInt32.from(0),
7675
+ current_task_remaining: UInt32.from(0),
7676
+ pending_tasks: [],
7677
+ schedule: state.schedule,
7678
+ });
7679
+ return new Container(entityInfo);
7449
7680
  }
7450
7681
 
7451
7682
  function totalCargoMass(cargo) {
@@ -7686,7 +7917,7 @@ const categories = [
7686
7917
  {
7687
7918
  id: 'precious',
7688
7919
  name: 'Precious Metals',
7689
- label: 'Precious',
7920
+ label: 'Precious Metal',
7690
7921
  description: 'Conductive, corrosion-resistant — electronics, energy systems, precision components',
7691
7922
  color: categoryColors.precious,
7692
7923
  },
@@ -8755,5 +8986,5 @@ var index = /*#__PURE__*/Object.freeze({
8755
8986
  buildEntityDescription: buildEntityDescription
8756
8987
  });
8757
8988
 
8758
- export { ActionsManager, BASE_ORBITAL_MASS, COMMIT_ALREADY_SET, COMMIT_CANNOT_MATCH, COMMIT_NOT_SET, COMPANY_NOT_FOUND, CONTAINER_Z, CRAFT_ENERGY_DIVISOR, Container, Coordinates, DEPTH_THRESHOLD_T1, DEPTH_THRESHOLD_T2, DEPTH_THRESHOLD_T3, DEPTH_THRESHOLD_T4, DEPTH_THRESHOLD_T5, EPOCH_NON_ZERO, EPOCH_NOT_READY, ERROR_SYSTEM_ALREADY_INITIALIZED, ERROR_SYSTEM_DISABLED, ERROR_SYSTEM_NOT_INITIALIZED, EntitiesManager, EntityInventory, EntityType, EpochsManager, GAME_NOT_FOUND, GAME_SEED_NOT_SET, GameState, INITIAL_CONTAINER_CAPACITY, INITIAL_CONTAINER_HULLMASS, INITIAL_WAREHOUSE_CAPACITY, INSUFFICIENT_BALANCE, INSUFFICIENT_ITEM_QUANTITY, INSUFFICIENT_ITEM_SUPPLY, INVALID_AMOUNT, ITEM_CARGO_ARM, ITEM_CARGO_LINING, ITEM_CARGO_LINING_T2, ITEM_CONTAINER_T1_PACKED, ITEM_CONTAINER_T2_PACKED, ITEM_DOES_NOT_EXIST, ITEM_ENGINE_T1, ITEM_FOCUSING_ARRAY, ITEM_GATHERER_T1, ITEM_GENERATOR_T1, ITEM_HAULER_T1, ITEM_HULL_PLATES, ITEM_HULL_PLATES_T2, ITEM_LOADER_T1, ITEM_MANUFACTURING_T1, ITEM_MATTER_CONDUIT, ITEM_NOT_AVAILABLE_AT_LOCATION, ITEM_POWER_CELL, ITEM_REACTION_CHAMBER, ITEM_SHIP_T1_PACKED, ITEM_STORAGE_T1, ITEM_SURVEY_PROBE, ITEM_THRUSTER_CORE, ITEM_TOOL_BIT, ITEM_TYPE_COMPONENT, ITEM_TYPE_ENTITY, ITEM_TYPE_MODULE, ITEM_TYPE_RESOURCE, ITEM_WAREHOUSE_T1_PACKED, InventoryAccessor, Item, LOCATION_MAX_DEPTH, LOCATION_MIN_DEPTH, Location, LocationType, LocationsManager, MAX_ORBITAL_ALTITUDE, MIN_ORBITAL_ALTITUDE, MODULE_ANY, MODULE_CRAFTER, MODULE_ENGINE, MODULE_GATHERER, MODULE_GENERATOR, MODULE_HAULER, MODULE_LAUNCHER, MODULE_LOADER, MODULE_STORAGE, MODULE_WARP, index as NFT, NO_SCHEDULE, PLANET_SUBTYPE_GAS_GIANT, PLANET_SUBTYPE_ICY, PLANET_SUBTYPE_INDUSTRIAL, PLANET_SUBTYPE_OCEAN, PLANET_SUBTYPE_ROCKY, PLANET_SUBTYPE_TERRESTRIAL, PLAYER_ALREADY_JOINED, PLAYER_NOT_FOUND, PRECISION$1 as PRECISION, platform as PlatformContract, Player, PlayersManager, REQUIRES_MORE_THAN_ONE, REQUIRES_POSITIVE_VALUE, SHIP_ALREADY_THERE, SHIP_ALREADY_TRAVELING, SHIP_CANNOT_BUY_TRAVELING, SHIP_CANNOT_CANCEL_TASK, SHIP_CANNOT_UPDATE_TRAVELING, SHIP_CARGO_NOT_LOADED, SHIP_CARGO_NOT_OWNED, SHIP_INVALID_CARGO, SHIP_INVALID_DESTINATION, SHIP_INVALID_TRAVEL_DURATION, SHIP_NOT_ARRIVED, SHIP_NOT_ENOUGH_ENERGY, SHIP_NOT_ENOUGH_ENERGY_CAPACITY, SHIP_NOT_FOUND, SHIP_NOT_IDLE, SHIP_NOT_OWNED, SHIP_NO_COMPLETED_TASKS, SHIP_NO_TASKS_TO_CANCEL, ScheduleAccessor, server as ServerContract, Ship, Shipload, TRAVEL_MAX_DURATION, TaskCancelable, TaskType, WAREHOUSE_ALREADY_AT_LOCATION, WAREHOUSE_CAPACITY_EXCEEDED, WAREHOUSE_NOT_FOUND, WAREHOUSE_Z, Warehouse, availableCapacity$1 as availableCapacity, availableCapacityFromMass, blendCargoStacks, blendComponentStacks, blendCrossGroup, blendStacks, buildEntityDescription, calcCargoItemMass, calcCargoMass, calcEnergyUsage, calcLoadDuration, calc_acceleration, calc_craft_duration, calc_craft_energy, calc_energyusage, calc_flighttime, calc_gather_duration, calc_gather_energy, calc_loader_acceleration, calc_loader_flighttime, calc_orbital_altitude, calc_rechargetime, calc_ship_acceleration, calc_ship_flighttime, calc_ship_mass, calc_ship_rechargetime, calc_transfer_duration, calculateFlightTime, calculateLoadTimeBreakdown, calculateRefuelingTime, calculateTransferTime, canMove, capabilityAttributes, capabilityNames, capsHasCrafter, capsHasGatherer, capsHasLoaders, capsHasMass, capsHasMovement, capsHasStorage, cargoUtils, categoryColors, categoryIcons, categoryItemMass, componentIcon, components, computeBaseCapacityShip, computeBaseCapacityWarehouse, computeBaseHullmass, computeComponentStats, computeContainerCapabilities, computeContainerT2Capabilities, computeCrafterDrain, computeCrafterSpeed, computeEngineCapabilities, computeEngineDrain, computeEngineThrust, computeEntityStats, computeGathererCapabilities, computeGathererDepth, computeGathererDrain, computeGathererSpeed, computeGathererYield, computeGeneratorCap, computeGeneratorCapabilities, computeGeneratorRech, computeHaulPenalty, computeHaulerCapabilities, computeHaulerDrain, computeInputMass, computeLoaderCapabilities, computeLoaderMass, computeLoaderThrust, computeManufacturingCapabilities, computeShipCapabilities, computeShipHullCapabilities, computeStorageCapabilities, computeWarehouseHullCapabilities, coordsToLocationId, createInventoryAccessor, createProjectedEntity, createScheduleAccessor, decodeCraftedItemStats, decodeStat, decodeStats, Shipload as default, depthScaleFactor, deriveLocation, deriveLocationEpoch, deriveLocationSize, deriveLocationStatic, deriveResourceStats, deriveStratum, deserializeAsset, deserializeComponent, deserializeEntity, deserializeModule, deserializeResource, distanceBetweenCoordinates, distanceBetweenPoints, encodeStats, energyPercent, entityDisplayName, entityRecipes, estimateDealTravelTime, estimateTravelTime, findNearbyPlanets, formatModuleLine, getAllCraftableItems, getCapabilityAttributes, getCategoryInfo, getComponentById, getComponentsForCategory, getComponentsForStat, getCurrentEpoch, getDepthThreshold, getDestinationLocation, getEligibleResources, getEntityRecipe, getEntityRecipeByItemId, getEntitySlotLayout, getEpochInfo, getFlightOrigin, getItem, getItems, getLocationCandidates, getLocationType, getLocationTypeName, getModuleCapabilityType, getModuleRecipe, getModuleRecipeByItemId, getPlanetSubtype, getPlanetSubtypes, getPositionAt, getResourceTier, getResourceWeight, getStatDefinitions, getStatMappings, getStatMappingsForCapability, getStatMappingsForStat, getStatName, getSystemName, hasEnergy, hasEnergyForDistance$1 as hasEnergyForDistance, hasGatherer, hasLoaders, hasMass, hasSchedule, hasSpace$1 as hasSpace, hasSpaceForMass, hasStorage, hasSystem, hash, hash512, isCraftedItem, isFull$1 as isFull, isFullFromMass, isGatherableLocation, isInvertedAttribute, isModuleItem, isRelatedItem, itemCategory, itemIcons, itemIds, itemOffset, itemTier, itemTypeCode, lerp, makeContainer, makeShip, makeWarehouse, maxTravelDistance, moduleAccepts, moduleDisplayName, moduleIcon, moduleRecipes, needsRecharge, projectEntity, projectEntityAt, readCommonBase, resolveItem, resolveStats, rotation, schedule, statMappings, tierColors, toLocation };
8989
+ export { ActionsManager, BASE_ORBITAL_MASS, COMMIT_ALREADY_SET, COMMIT_CANNOT_MATCH, COMMIT_NOT_SET, COMPANY_NOT_FOUND, CONTAINER_Z, CRAFT_ENERGY_DIVISOR, Container, Coordinates, DEPTH_THRESHOLD_T1, DEPTH_THRESHOLD_T2, DEPTH_THRESHOLD_T3, DEPTH_THRESHOLD_T4, DEPTH_THRESHOLD_T5, ENTITY_CAPACITY_EXCEEDED, EPOCH_NON_ZERO, EPOCH_NOT_READY, ERROR_SYSTEM_ALREADY_INITIALIZED, ERROR_SYSTEM_DISABLED, ERROR_SYSTEM_NOT_INITIALIZED, EntitiesManager, EntityInventory, EntityType, EpochsManager, GAME_NOT_FOUND, GAME_SEED_NOT_SET, GameState, INITIAL_CONTAINER_CAPACITY, INITIAL_CONTAINER_HULLMASS, INITIAL_WAREHOUSE_CAPACITY, INSUFFICIENT_BALANCE, INSUFFICIENT_ITEM_QUANTITY, INSUFFICIENT_ITEM_SUPPLY, INVALID_AMOUNT, ITEM_CARGO_ARM, ITEM_CARGO_LINING, ITEM_CARGO_LINING_T2, ITEM_CONTAINER_T1_PACKED, ITEM_CONTAINER_T2_PACKED, ITEM_DOES_NOT_EXIST, ITEM_ENGINE_T1, ITEM_FOCUSING_ARRAY, ITEM_GATHERER_T1, ITEM_GENERATOR_T1, ITEM_HAULER_T1, ITEM_HULL_PLATES, ITEM_HULL_PLATES_T2, ITEM_LOADER_T1, ITEM_MANUFACTURING_T1, ITEM_MATTER_CONDUIT, ITEM_NOT_AVAILABLE_AT_LOCATION, ITEM_POWER_CELL, ITEM_REACTION_CHAMBER, ITEM_SHIP_T1_PACKED, ITEM_STORAGE_T1, ITEM_SURVEY_PROBE, ITEM_THRUSTER_CORE, ITEM_TOOL_BIT, ITEM_TYPE_COMPONENT, ITEM_TYPE_ENTITY, ITEM_TYPE_MODULE, ITEM_TYPE_RESOURCE, ITEM_WAREHOUSE_T1_PACKED, InventoryAccessor, Item, LOCATION_MAX_DEPTH, LOCATION_MIN_DEPTH, Location, LocationType, LocationsManager, MAX_ORBITAL_ALTITUDE, MIN_ORBITAL_ALTITUDE, MODULE_ANY, MODULE_CRAFTER, MODULE_ENGINE, MODULE_GATHERER, MODULE_GENERATOR, MODULE_HAULER, MODULE_LAUNCHER, MODULE_LOADER, MODULE_STORAGE, MODULE_WARP, index as NFT, NO_SCHEDULE, PLANET_SUBTYPE_GAS_GIANT, PLANET_SUBTYPE_ICY, PLANET_SUBTYPE_INDUSTRIAL, PLANET_SUBTYPE_OCEAN, PLANET_SUBTYPE_ROCKY, PLANET_SUBTYPE_TERRESTRIAL, PLAYER_ALREADY_JOINED, PLAYER_NOT_FOUND, PRECISION$1 as PRECISION, platform as PlatformContract, Player, PlayersManager, RECIPE_INPUTS_EXCESS, RECIPE_INPUTS_INSUFFICIENT, RECIPE_INPUTS_INVALID, RECIPE_INPUTS_MIXED, REQUIRES_MORE_THAN_ONE, REQUIRES_POSITIVE_VALUE, RESERVE_TIERS, SHIP_ALREADY_THERE, SHIP_ALREADY_TRAVELING, SHIP_CANNOT_BUY_TRAVELING, SHIP_CANNOT_CANCEL_TASK, SHIP_CANNOT_UPDATE_TRAVELING, SHIP_CARGO_NOT_LOADED, SHIP_CARGO_NOT_OWNED, SHIP_INVALID_CARGO, SHIP_INVALID_DESTINATION, SHIP_INVALID_TRAVEL_DURATION, SHIP_NOT_ARRIVED, SHIP_NOT_ENOUGH_ENERGY, SHIP_NOT_ENOUGH_ENERGY_CAPACITY, SHIP_NOT_FOUND, SHIP_NOT_IDLE, SHIP_NOT_OWNED, SHIP_NO_COMPLETED_TASKS, SHIP_NO_TASKS_TO_CANCEL, ScheduleAccessor, server as ServerContract, Ship, Shipload, TIER_ROLL_MAX, TRAVEL_MAX_DURATION, TaskCancelable, TaskType, WAREHOUSE_ALREADY_AT_LOCATION, WAREHOUSE_CAPACITY_EXCEEDED, WAREHOUSE_NOT_FOUND, WAREHOUSE_Z, Warehouse, availableCapacity$1 as availableCapacity, availableCapacityFromMass, blendCargoStacks, blendComponentStacks, blendCrossGroup, blendStacks, buildEntityDescription, calcCargoItemMass, calcCargoMass, calcEnergyUsage, calcLoadDuration, calcStacksMass, calc_acceleration, calc_craft_duration, calc_craft_energy, calc_energyusage, calc_flighttime, calc_gather_duration, calc_gather_energy, calc_loader_acceleration, calc_loader_flighttime, calc_orbital_altitude, calc_rechargetime, calc_ship_acceleration, calc_ship_flighttime, calc_ship_mass, calc_ship_rechargetime, calc_transfer_duration, calculateFlightTime, calculateLoadTimeBreakdown, calculateRefuelingTime, calculateTransferTime, canMove, capabilityAttributes, capabilityNames, capsHasCrafter, capsHasGatherer, capsHasLoaders, capsHasMass, capsHasMovement, capsHasStorage, cargoItemToStack, cargoUtils, categoryColors, categoryIcons, categoryItemMass, componentIcon, components, computeBaseCapacityShip, computeBaseCapacityWarehouse, computeBaseHullmass, computeComponentStats, computeContainerCapabilities, computeContainerT2Capabilities, computeCraftedOutputSeed, computeCrafterDrain, computeCrafterSpeed, computeEngineCapabilities, computeEngineDrain, computeEngineThrust, computeEntityStats, computeGathererCapabilities, computeGathererDepth, computeGathererDrain, computeGathererSpeed, computeGathererYield, computeGeneratorCap, computeGeneratorCapabilities, computeGeneratorRech, computeHaulPenalty, computeHaulerCapabilities, computeHaulerDrain, computeInputMass, computeLoaderCapabilities, computeLoaderMass, computeLoaderThrust, computeManufacturingCapabilities, computeShipCapabilities, computeShipHullCapabilities, computeStorageCapabilities, computeWarehouseHullCapabilities, coordsToLocationId, createInventoryAccessor, createProjectedEntity, createScheduleAccessor, decodeCraftedItemStats, decodeStat, decodeStats, Shipload as default, deriveLocation, deriveLocationEpoch, deriveLocationSize, deriveLocationStatic, deriveResourceStats, deriveStratum, deserializeAsset, deserializeComponent, deserializeEntity, deserializeModule, deserializeResource, distanceBetweenCoordinates, distanceBetweenPoints, encodeStats, energyPercent, entityDisplayName, entityRecipes, estimateDealTravelTime, estimateTravelTime, findNearbyPlanets, formatModuleLine, getAllCraftableItems, getCapabilityAttributes, getCategoryInfo, getComponentById, getComponentsForCategory, getComponentsForStat, getCurrentEpoch, getDepthThreshold, getDestinationLocation, getEligibleResources, getEntityRecipe, getEntityRecipeByItemId, getEntitySlotLayout, getEpochInfo, getFlightOrigin, getItem, getItems, getLocationCandidates, getLocationType, getLocationTypeName, getModuleCapabilityType, getModuleRecipe, getModuleRecipeByItemId, getPlanetSubtype, getPlanetSubtypes, getPositionAt, getResourceTier, getResourceWeight, getStatDefinitions, getStatMappings, getStatMappingsForCapability, getStatMappingsForStat, getStatName, getSystemName, hasEnergy, hasEnergyForDistance$1 as hasEnergyForDistance, hasGatherer, hasLoaders, hasMass, hasSchedule, hasSpace$1 as hasSpace, hasSpaceForMass, hasStorage, hasSystem, hash, hash512, isCraftedItem, isFull$1 as isFull, isFullFromMass, isGatherableLocation, isInvertedAttribute, isModuleItem, isRelatedItem, itemCategory, itemIcons, itemIds, itemOffset, itemTier, itemTypeCode, lerp, makeContainer, makeShip, makeWarehouse, maxTravelDistance, mergeStacks, moduleAccepts, moduleDisplayName, moduleIcon, moduleRecipes, needsRecharge, projectEntity, projectEntityAt, readCommonBase, removeFromStacks, resolveItem, resolveStats, rollTier, rollWithinTier, rotation, schedule, stackKey, stackToCargoItem, stacksEqual, statMappings, tierColors, toLocation, validateSchedule };
8759
8990
  //# sourceMappingURL=shipload.m.js.map