@shipload/sdk 1.0.0-next.25 → 1.0.0-next.26

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.
@@ -55,7 +55,7 @@ export const GATHERER_DEPTH_TABLE: readonly GathererDepthParams[] = [
55
55
  {floor: 46000, slope: 12},
56
56
  {floor: 53500, slope: 10},
57
57
  {floor: 60000, slope: 5},
58
- {floor: 63500, slope: 2},
58
+ {floor: 63537, slope: 2},
59
59
  ]
60
60
 
61
61
  export const GATHERER_DEPTH_MAX_TIER = 10
@@ -175,6 +175,7 @@ import {decodeCraftedItemStats} from './crafting'
175
175
  import {
176
176
  applySlotMultiplier,
177
177
  clampUint16,
178
+ clampUint32,
178
179
  getSlotAmp,
179
180
  type InstalledModule,
180
181
  } from '../entities/slot-multiplier'
@@ -346,8 +347,8 @@ export function computeEntityCapabilities(
346
347
  }
347
348
  if (hasGenerator) {
348
349
  result.generator = {
349
- capacity: clampUint16(totalGenCapacity),
350
- recharge: clampUint16(totalGenRecharge),
350
+ capacity: clampUint32(totalGenCapacity),
351
+ recharge: clampUint32(totalGenRecharge),
351
352
  }
352
353
  }
353
354
  if (hasGatherer) {
@@ -28,6 +28,8 @@ export function clampUint16(value: number): number {
28
28
  return Math.min(value, U16_MAX)
29
29
  }
30
30
 
31
+ export const clampUint32 = (v: number): number => Math.min(Math.max(Math.floor(v), 0), 4294967295)
32
+
31
33
  export function applySlotMultiplier(value: number, outputPct: number): number {
32
34
  return clampUint16(Math.floor((value * outputPct) / 100))
33
35
  }
@@ -252,6 +252,12 @@ export class ActionsManager extends BaseManager {
252
252
  })
253
253
  }
254
254
 
255
+ claimStarter(owner: NameType): Action {
256
+ return this.server.action('claimstarter', {
257
+ owner: Name.from(owner),
258
+ })
259
+ }
260
+
255
261
  async wrapEntity(
256
262
  owner: NameType,
257
263
  entityId: UInt64Type,
@@ -67,7 +67,8 @@ export interface ScheduledBuild {
67
67
  hasStarted: boolean
68
68
  startsAt: number
69
69
  completesAt: number
70
- trailingCancelCount: number
70
+ cancelable: boolean
71
+ blockingTaskCount: number
71
72
  }
72
73
 
73
74
  export interface Reservation {
@@ -142,51 +142,105 @@ export class ConstructionManager extends BaseManager {
142
142
  return out
143
143
  }
144
144
 
145
+ private plotReservation(
146
+ plot: ServerContract.Types.entity_info,
147
+ now: Date
148
+ ): {
149
+ builderId: UInt64
150
+ group?: UInt64
151
+ startsAt: number
152
+ completesAt: number
153
+ hasStarted: boolean
154
+ } | null {
155
+ const schedule = plot.schedule
156
+ if (!schedule) return null
157
+ const tasks = schedule.tasks
158
+ const startedMs = schedule.started.toDate().getTime()
159
+ let startSec = 0
160
+ for (const task of tasks) {
161
+ if (task.type.toNumber() === TaskType.RESERVED) {
162
+ if (!task.entitytarget) return null
163
+ const startsAt = startedMs + startSec * 1000
164
+ const completesAt = startsAt + task.duration.toNumber() * 1000
165
+ return {
166
+ builderId: task.entitytarget.entity_id,
167
+ group: task.entitygroup ?? undefined,
168
+ startsAt,
169
+ completesAt,
170
+ hasStarted: startsAt <= now.getTime(),
171
+ }
172
+ }
173
+ startSec += task.duration.toNumber()
174
+ }
175
+ return null
176
+ }
177
+
178
+ private builderCancelability(
179
+ builder: ServerContract.Types.entity_info | undefined,
180
+ group: UInt64 | undefined
181
+ ): {cancelable: boolean; blockingTaskCount: number} {
182
+ if (!builder?.schedule || group === undefined) {
183
+ return {cancelable: false, blockingTaskCount: 0}
184
+ }
185
+ const tasks = builder.schedule.tasks
186
+ const buildIdx = tasks.findIndex(
187
+ (t) =>
188
+ t.type.toNumber() === TaskType.BUILDPLOT &&
189
+ t.entitygroup !== undefined &&
190
+ t.entitygroup.equals(group)
191
+ )
192
+ if (buildIdx < 0) return {cancelable: false, blockingTaskCount: 0}
193
+ const trailing = tasks.length - 1 - buildIdx
194
+ return {cancelable: trailing === 0, blockingTaskCount: trailing}
195
+ }
196
+
197
+ private buildFromReservation(
198
+ res: {
199
+ builderId: UInt64
200
+ group?: UInt64
201
+ startsAt: number
202
+ completesAt: number
203
+ hasStarted: boolean
204
+ },
205
+ builder: ServerContract.Types.entity_info | undefined
206
+ ): ScheduledBuild {
207
+ const {cancelable, blockingTaskCount} = this.builderCancelability(builder, res.group)
208
+ return {
209
+ shipId: res.builderId,
210
+ shipName: builder?.entity_name || res.builderId.toString(),
211
+ hasStarted: res.hasStarted,
212
+ startsAt: res.startsAt,
213
+ completesAt: res.completesAt,
214
+ cancelable,
215
+ blockingTaskCount,
216
+ }
217
+ }
218
+
145
219
  scheduledBuildFor(
146
- plotId: UInt64,
220
+ plot: ServerContract.Types.entity_info,
147
221
  entities: ServerContract.Types.entity_info[],
148
222
  now: Date
149
223
  ): ScheduledBuild | null {
150
- return this.scheduledBuildsByTarget(entities, now).get(plotId.toString()) ?? null
224
+ const res = this.plotReservation(plot, now)
225
+ if (!res) return null
226
+ const builder = entities.find((e) => e.id.equals(res.builderId))
227
+ return this.buildFromReservation(res, builder)
151
228
  }
152
229
 
153
230
  scheduledBuildsByTarget(
154
231
  entities: ServerContract.Types.entity_info[],
155
232
  now: Date
156
233
  ): Map<string, ScheduledBuild> {
157
- const nowMs = now.getTime()
158
- const best = new Map<string, ScheduledBuild>()
234
+ const byId = new Map(entities.map((e) => [e.id.toString(), e]))
235
+ const out = new Map<string, ScheduledBuild>()
159
236
  for (const entity of entities) {
160
- const schedule = entity.schedule
161
- if (!schedule) continue
162
- const startedMs = schedule.started.toDate().getTime()
163
- const tasks = schedule.tasks
164
- let cumulativeSec = 0
165
- for (let i = 0; i < tasks.length; i++) {
166
- const task = tasks[i]
167
- const startSec = cumulativeSec
168
- cumulativeSec += task.duration.toNumber()
169
- if (task.type.toNumber() !== TaskType.BUILDPLOT) continue
170
- if (!task.entitytarget) continue
171
- const completesAt = startedMs + cumulativeSec * 1000
172
- if (completesAt < nowMs) continue
173
- const startsAt = startedMs + startSec * 1000
174
- const targetId = task.entitytarget.entity_id.toString()
175
- const candidate: ScheduledBuild = {
176
- shipId: entity.id,
177
- shipName: entity.entity_name || entity.id.toString(),
178
- hasStarted: startsAt <= nowMs,
179
- startsAt,
180
- completesAt,
181
- trailingCancelCount: tasks.length - 1 - i,
182
- }
183
- const existing = best.get(targetId)
184
- if (!existing || candidate.completesAt < existing.completesAt) {
185
- best.set(targetId, candidate)
186
- }
187
- }
237
+ if (entity.type.toString() !== 'plot') continue
238
+ const res = this.plotReservation(entity, now)
239
+ if (!res) continue
240
+ const builder = byId.get(res.builderId.toString())
241
+ out.set(entity.id.toString(), this.buildFromReservation(res, builder))
188
242
  }
189
- return best
243
+ return out
190
244
  }
191
245
 
192
246
  reservationsFrom(
@@ -60,7 +60,10 @@ export function scheduleRemaining(entity: ScheduleData, now: Date): number {
60
60
  }
61
61
 
62
62
  export function scheduleComplete(entity: ScheduleData, now: Date): boolean {
63
- return hasSchedule(entity) && scheduleRemaining(entity, now) === 0
63
+ if (!hasSchedule(entity)) return false
64
+ if ((entity.schedule?.tasks ?? []).some((t) => t.type.toNumber() === TaskType.RESERVED))
65
+ return false
66
+ return scheduleRemaining(entity, now) === 0
64
67
  }
65
68
 
66
69
  export function currentTaskIndex(entity: ScheduleData, now: Date): number {
@@ -124,6 +127,8 @@ export function getTaskRemaining(entity: ScheduleData, index: number, now: Date)
124
127
  export function isTaskComplete(entity: ScheduleData, index: number, now: Date): boolean {
125
128
  if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length) return false
126
129
 
130
+ if (entity.schedule.tasks[index].type.toNumber() === TaskType.RESERVED) return false
131
+
127
132
  const taskDuration = entity.schedule.tasks[index].duration.toNumber()
128
133
  const taskElapsed = getTaskElapsed(entity, index, now)
129
134
  return taskElapsed >= taskDuration
@@ -1,8 +0,0 @@
1
- import {UInt32, type UInt64} from '@wharfkit/antelope'
2
- import type {LoaderCapability} from '../types/capabilities'
3
-
4
- export function calcLoadDuration(entity: LoaderCapability, cargoMass: UInt64): UInt32 {
5
- const totalThrust = entity.loaders.thrust.toNumber() * entity.loaders.quantity.toNumber()
6
- if (totalThrust === 0) return UInt32.from(0)
7
- return UInt32.from(Math.ceil(Number(cargoMass) / totalThrust))
8
- }