@shipload/sdk 1.0.0-next.6 → 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.
@@ -90,18 +90,15 @@ export class ActionsManager extends BaseManager {
90
90
  sourceId: UInt64Type,
91
91
  destType: EntityTypeName,
92
92
  destId: UInt64Type,
93
- itemId: UInt64Type,
94
- stats: UInt64Type,
95
- quantity: UInt64Type
93
+ items: ServerContract.ActionParams.Type.cargo_item[]
96
94
  ): Action {
95
+ const cargoItems = items.map((i) => ServerContract.Types.cargo_item.from(i))
97
96
  return this.server.action('transfer', {
98
97
  source_type: sourceType,
99
98
  source_id: UInt64.from(sourceId),
100
99
  dest_type: destType,
101
100
  dest_id: UInt64.from(destId),
102
- item_id: UInt16.from(itemId),
103
- stats: UInt64.from(stats),
104
- quantity: UInt32.from(quantity),
101
+ items: cargoItems,
105
102
  })
106
103
  }
107
104
 
@@ -187,14 +184,12 @@ export class ActionsManager extends BaseManager {
187
184
  deploy(
188
185
  entityType: EntityTypeName,
189
186
  entityId: UInt64Type,
190
- packedItemId: number,
191
- stats: bigint
187
+ ref: ServerContract.ActionParams.Type.cargo_ref
192
188
  ): Action {
193
189
  return this.server.action('deploy', {
194
190
  entity_type: entityType,
195
191
  id: UInt64.from(entityId),
196
- packed_item_id: UInt16.from(packedItemId),
197
- stats: UInt64.from(stats),
192
+ ref: ServerContract.Types.cargo_ref.from(ref),
198
193
  })
199
194
  }
200
195
 
@@ -202,15 +197,15 @@ export class ActionsManager extends BaseManager {
202
197
  entityType: EntityTypeName,
203
198
  entityId: UInt64Type,
204
199
  moduleIndex: number,
205
- moduleCargoId: UInt64Type,
206
- targetCargoId: UInt64Type = UInt64.from(0)
200
+ moduleRef: ServerContract.ActionParams.Type.cargo_ref,
201
+ targetRef: ServerContract.ActionParams.Type.cargo_ref | null = null
207
202
  ): Action {
208
203
  return this.server.action('addmodule', {
209
204
  entity_type: entityType,
210
205
  entity_id: UInt64.from(entityId),
211
206
  module_index: moduleIndex,
212
- module_cargo_id: UInt64.from(moduleCargoId),
213
- target_cargo_id: UInt64.from(targetCargoId),
207
+ module_ref: ServerContract.Types.cargo_ref.from(moduleRef),
208
+ target_ref: targetRef ? ServerContract.Types.cargo_ref.from(targetRef) : null,
214
209
  })
215
210
  }
216
211
 
@@ -218,13 +213,13 @@ export class ActionsManager extends BaseManager {
218
213
  entityType: EntityTypeName,
219
214
  entityId: UInt64Type,
220
215
  moduleIndex: number,
221
- targetCargoId: UInt64Type = UInt64.from(0)
216
+ targetRef: ServerContract.ActionParams.Type.cargo_ref | null = null
222
217
  ): Action {
223
218
  return this.server.action('rmmodule', {
224
219
  entity_type: entityType,
225
220
  entity_id: UInt64.from(entityId),
226
221
  module_index: moduleIndex,
227
- target_cargo_id: UInt64.from(targetCargoId),
222
+ target_ref: targetRef ? ServerContract.Types.cargo_ref.from(targetRef) : null,
228
223
  })
229
224
  }
230
225
 
@@ -232,15 +227,14 @@ export class ActionsManager extends BaseManager {
232
227
  owner: NameType,
233
228
  entityType: EntityTypeName,
234
229
  entityId: UInt64Type,
235
- cargoId: UInt64Type,
236
- quantity: UInt64Type
230
+ items: ServerContract.ActionParams.Type.cargo_item[]
237
231
  ): Action {
232
+ const cargoItems = items.map((i) => ServerContract.Types.cargo_item.from(i))
238
233
  return this.server.action('wrap', {
239
234
  owner: Name.from(owner),
240
235
  entity_type: entityType,
241
236
  entity_id: UInt64.from(entityId),
242
- cargo_id: UInt64.from(cargoId),
243
- quantity: UInt64.from(quantity),
237
+ items: cargoItems,
244
238
  })
245
239
  }
246
240
 
@@ -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
@@ -163,3 +165,7 @@ export interface Item {
163
165
  export function formatTier(tier: number): string {
164
166
  return 'T' + tier
165
167
  }
168
+
169
+ export function tierAdjective(tier: number): string {
170
+ return TIER_ADJECTIVES[tier] ?? `T${tier}`
171
+ }
@@ -0,0 +1,27 @@
1
+ import type {ServerContract} from '../contracts'
2
+
3
+ export function cargoRef(src: {
4
+ item_id: number
5
+ stats: bigint | number
6
+ modules?: ServerContract.Types.module_entry[]
7
+ }): ServerContract.ActionParams.Type.cargo_ref {
8
+ return {
9
+ item_id: src.item_id,
10
+ stats: src.stats,
11
+ modules: src.modules ?? [],
12
+ }
13
+ }
14
+
15
+ export function cargoItem(
16
+ src: {
17
+ item_id: number
18
+ stats: bigint | number
19
+ modules?: ServerContract.Types.module_entry[]
20
+ },
21
+ quantity: bigint | number
22
+ ): ServerContract.ActionParams.Type.cargo_item {
23
+ return {
24
+ ...cargoRef(src),
25
+ quantity,
26
+ }
27
+ }
@@ -8,7 +8,6 @@ import nebulaAdjectives from '../data/nebula-adjectives.json'
8
8
  import nebulaNouns from '../data/nebula-nouns.json'
9
9
 
10
10
  const LOCATION_EXISTS_THRESHOLD = 0x10
11
- const LOCATION_ACTIVE_THRESHOLD = 0x80
12
11
 
13
12
  export function getLocationType(
14
13
  gameSeed: Checksum256Type,
@@ -151,31 +150,20 @@ export function deriveLocationStatic(
151
150
  return loc
152
151
  }
153
152
 
154
- export function deriveLocationEpoch(
155
- epochSeed: Checksum256Type,
153
+ export function isLocationBuildable(
154
+ gameSeed: Checksum256Type,
156
155
  coordinates: CoordinatesType
157
- ): ServerContract.Types.location_epoch {
158
- const seed = Checksum256.from(epochSeed)
159
- const coords = Coordinates.from(coordinates)
160
- const str = `system-epoch-${coords.x}-${coords.y}`
161
- const hashResult = hash512(seed, str)
162
-
163
- return ServerContract.Types.location_epoch.from({
164
- active: hashResult.array[0] < LOCATION_ACTIVE_THRESHOLD,
165
- seed0: hashResult.array[1],
166
- seed1: hashResult.array[2],
167
- })
156
+ ): boolean {
157
+ return getLocationType(gameSeed, coordinates) === LocationType.PLANET
168
158
  }
169
159
 
170
160
  export function deriveLocation(
171
161
  gameSeed: Checksum256Type,
172
- epochSeed: Checksum256Type,
173
162
  coordinates: CoordinatesType
174
163
  ): ServerContract.Types.location_derived {
175
164
  const staticProps = deriveLocationStatic(gameSeed, coordinates)
176
165
  return ServerContract.Types.location_derived.from({
177
166
  static_props: staticProps,
178
- epoch_props: deriveLocationEpoch(epochSeed, coordinates),
179
167
  size: deriveLocationSize(staticProps),
180
168
  })
181
169
  }