@shipload/sdk 1.0.0-next.7 → 1.0.0-next.8

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipload/sdk",
3
3
  "description": "SDKs for Shipload",
4
- "version": "1.0.0-next.7",
4
+ "version": "1.0.0-next.8",
5
5
  "homepage": "https://github.com/shipload/toolkit/tree/master/packages/sdk",
6
6
  "repository": {
7
7
  "type": "git",
@@ -71,6 +71,7 @@ export {
71
71
  getLocationType,
72
72
  getLocationTypeName,
73
73
  isGatherableLocation,
74
+ isLocationBuildable,
74
75
  deriveLocationStatic,
75
76
  deriveLocation,
76
77
  } from './utils/system'
@@ -179,8 +180,16 @@ export type {
179
180
  ProjectionOptions,
180
181
  } from './scheduling/projection'
181
182
 
183
+ export {predictTaskCargoEffects} from './scheduling/predict-cargo'
184
+ export type {
185
+ PredictedCargoAddition,
186
+ PredictedCargoTarget,
187
+ TaskCargoEffect,
188
+ } from './scheduling/predict-cargo'
189
+
182
190
  export * from './types/capabilities'
183
191
  export * from './types/entity'
192
+ export {EntityClass, getEntityClass, getPackedEntityType} from './types/entity-traits'
184
193
  export * from './capabilities'
185
194
 
186
195
  export {
@@ -0,0 +1,151 @@
1
+ import type {ServerContract} from '../contracts'
2
+ import {TaskType} from '../types'
3
+
4
+ export type PredictedCargoTarget = {kind: 'existing'; rowId: bigint} | {kind: 'new'; label: string}
5
+
6
+ export interface PredictedCargoAddition {
7
+ item_id: number
8
+ stats: bigint
9
+ modules: ServerContract.Types.module_entry[]
10
+ quantity: number
11
+ target: PredictedCargoTarget
12
+ }
13
+
14
+ export interface TaskCargoEffect {
15
+ additions: PredictedCargoAddition[]
16
+ }
17
+
18
+ interface StackState {
19
+ item_id: number
20
+ stats: bigint
21
+ modules: ServerContract.Types.module_entry[]
22
+ quantity: number
23
+ target: PredictedCargoTarget
24
+ }
25
+
26
+ function modulesEqual(
27
+ a: ServerContract.Types.module_entry[],
28
+ b: ServerContract.Types.module_entry[]
29
+ ): boolean {
30
+ if (a.length !== b.length) return false
31
+ for (let i = 0; i < a.length; i++) {
32
+ const ai = a[i]
33
+ const bi = b[i]
34
+ if (Number(ai.type) !== Number(bi.type)) return false
35
+ const aInst = ai.installed
36
+ const bInst = bi.installed
37
+ if (!aInst && !bInst) continue
38
+ if (!aInst || !bInst) return false
39
+ if (Number(aInst.item_id) !== Number(bInst.item_id)) return false
40
+ if (BigInt(aInst.stats.toString()) !== BigInt(bInst.stats.toString())) return false
41
+ }
42
+ return true
43
+ }
44
+
45
+ function findStack(
46
+ state: StackState[],
47
+ item_id: number,
48
+ stats: bigint,
49
+ modules: ServerContract.Types.module_entry[]
50
+ ): number {
51
+ for (let i = 0; i < state.length; i++) {
52
+ const s = state[i]
53
+ if (s.item_id !== item_id) continue
54
+ if (s.stats !== stats) continue
55
+ if (!modulesEqual(s.modules, modules)) continue
56
+ return i
57
+ }
58
+ return -1
59
+ }
60
+
61
+ function applyAddition(
62
+ state: StackState[],
63
+ item: ServerContract.Types.cargo_item,
64
+ nextNewLabel: () => string
65
+ ): PredictedCargoAddition {
66
+ const item_id = Number(item.item_id)
67
+ const stats = BigInt(item.stats.toString())
68
+ const modules = item.modules ?? []
69
+ const quantity = Number(item.quantity)
70
+
71
+ const idx = findStack(state, item_id, stats, modules)
72
+ if (idx === -1) {
73
+ const target: PredictedCargoTarget = {kind: 'new', label: nextNewLabel()}
74
+ state.push({item_id, stats, modules, quantity, target})
75
+ return {item_id, stats, modules, quantity, target}
76
+ }
77
+ state[idx].quantity += quantity
78
+ return {item_id, stats, modules, quantity, target: state[idx].target}
79
+ }
80
+
81
+ function applyRemoval(state: StackState[], item: ServerContract.Types.cargo_item): void {
82
+ const item_id = Number(item.item_id)
83
+ const stats = BigInt(item.stats.toString())
84
+ const modules = item.modules ?? []
85
+ const quantity = Number(item.quantity)
86
+
87
+ const idx = findStack(state, item_id, stats, modules)
88
+ if (idx === -1) return
89
+ state[idx].quantity -= quantity
90
+ if (state[idx].quantity <= 0) state.splice(idx, 1)
91
+ }
92
+
93
+ export function predictTaskCargoEffects(
94
+ cargo: readonly ServerContract.Types.cargo_view[],
95
+ tasks: readonly ServerContract.Types.task[]
96
+ ): TaskCargoEffect[] {
97
+ const state: StackState[] = cargo.map((c) => ({
98
+ item_id: Number(c.item_id),
99
+ stats: BigInt(c.stats.toString()),
100
+ modules: c.modules ?? [],
101
+ quantity: Number(c.quantity),
102
+ target: {kind: 'existing', rowId: BigInt(c.id.toString())},
103
+ }))
104
+
105
+ let newCounter = 0
106
+ const nextNewLabel = () => {
107
+ newCounter += 1
108
+ return `new#${newCounter}`
109
+ }
110
+
111
+ const effects: TaskCargoEffect[] = []
112
+
113
+ for (const task of tasks) {
114
+ const type = Number(task.type)
115
+ const items = task.cargo ?? []
116
+ const additions: PredictedCargoAddition[] = []
117
+
118
+ switch (type) {
119
+ case TaskType.LOAD:
120
+ case TaskType.UNWRAP: {
121
+ for (const item of items) additions.push(applyAddition(state, item, nextNewLabel))
122
+ break
123
+ }
124
+ case TaskType.GATHER: {
125
+ if (!task.entitytarget) {
126
+ for (const item of items)
127
+ additions.push(applyAddition(state, item, nextNewLabel))
128
+ }
129
+ break
130
+ }
131
+ case TaskType.UNLOAD:
132
+ case TaskType.WRAP: {
133
+ for (const item of items) applyRemoval(state, item)
134
+ break
135
+ }
136
+ case TaskType.CRAFT: {
137
+ if (items.length > 0) {
138
+ for (let i = 0; i < items.length - 1; i++) applyRemoval(state, items[i])
139
+ additions.push(applyAddition(state, items[items.length - 1], nextNewLabel))
140
+ }
141
+ break
142
+ }
143
+ default:
144
+ break
145
+ }
146
+
147
+ effects.push({additions})
148
+ }
149
+
150
+ return effects
151
+ }
@@ -28,6 +28,7 @@ import {
28
28
  type Distance,
29
29
  MAX_ORBITAL_ALTITUDE,
30
30
  MIN_ORBITAL_ALTITUDE,
31
+ MIN_TRANSFER_DISTANCE,
31
32
  PRECISION,
32
33
  type ShipLike,
33
34
  TaskType,
@@ -547,7 +548,8 @@ export function calc_transfer_duration(
547
548
  : (source.location.z?.toNumber() ?? 0)
548
549
  const destZ =
549
550
  typeof dest.location.z === 'number' ? dest.location.z : (dest.location.z?.toNumber() ?? 0)
550
- const distance = Math.abs(sourceZ - destZ)
551
+ const rawDistance = Math.abs(sourceZ - destZ)
552
+ const distance = rawDistance < MIN_TRANSFER_DISTANCE ? MIN_TRANSFER_DISTANCE : rawDistance
551
553
 
552
554
  const totalMass = cargoMass + totalLoaderMass
553
555
  const acceleration = calc_acceleration(totalThrust, totalMass)
@@ -1,9 +1,47 @@
1
1
  import {Name} from '@wharfkit/antelope'
2
+ import {
3
+ ITEM_CONTAINER_T1_PACKED,
4
+ ITEM_CONTAINER_T2_PACKED,
5
+ ITEM_SHIP_T1_PACKED,
6
+ ITEM_WAREHOUSE_T1_PACKED,
7
+ } from '../data/item-ids'
2
8
 
3
9
  export const ENTITY_SHIP = Name.from('ship')
4
10
  export const ENTITY_WAREHOUSE = Name.from('warehouse')
5
11
  export const ENTITY_CONTAINER = Name.from('container')
6
12
 
13
+ export enum EntityClass {
14
+ OrbitalVessel = 0,
15
+ PlanetaryStructure = 1,
16
+ }
17
+
18
+ export function getEntityClass(entityType: Name | EntityTypeName): EntityClass {
19
+ const typeName = typeof entityType === 'string' ? entityType : entityType.toString()
20
+ switch (typeName) {
21
+ case 'ship':
22
+ case 'container':
23
+ return EntityClass.OrbitalVessel
24
+ case 'warehouse':
25
+ return EntityClass.PlanetaryStructure
26
+ default:
27
+ throw new Error(`Entity type has no class: ${typeName}`)
28
+ }
29
+ }
30
+
31
+ export function getPackedEntityType(itemId: number): Name | null {
32
+ switch (itemId) {
33
+ case ITEM_SHIP_T1_PACKED:
34
+ return ENTITY_SHIP
35
+ case ITEM_CONTAINER_T1_PACKED:
36
+ case ITEM_CONTAINER_T2_PACKED:
37
+ return ENTITY_CONTAINER
38
+ case ITEM_WAREHOUSE_T1_PACKED:
39
+ return ENTITY_WAREHOUSE
40
+ default:
41
+ return null
42
+ }
43
+ }
44
+
7
45
  export type EntityTypeName = 'ship' | 'warehouse' | 'container'
8
46
 
9
47
  export interface EntityTraits {
package/src/types.ts CHANGED
@@ -23,6 +23,8 @@ export const MAX_ORBITAL_ALTITUDE = 3000
23
23
 
24
24
  export const BASE_ORBITAL_MASS = 100000
25
25
 
26
+ export const MIN_TRANSFER_DISTANCE = 100
27
+
26
28
  export interface ShipLike {
27
29
  coordinates: ServerContract.Types.coordinates
28
30
  hullmass?: UInt32
@@ -150,6 +150,13 @@ export function deriveLocationStatic(
150
150
  return loc
151
151
  }
152
152
 
153
+ export function isLocationBuildable(
154
+ gameSeed: Checksum256Type,
155
+ coordinates: CoordinatesType
156
+ ): boolean {
157
+ return getLocationType(gameSeed, coordinates) === LocationType.PLANET
158
+ }
159
+
153
160
  export function deriveLocation(
154
161
  gameSeed: Checksum256Type,
155
162
  coordinates: CoordinatesType