diff --git a/src/core/execution/TradeShipExecution.ts b/src/core/execution/TradeShipExecution.ts index b1771c46f..262ba3744 100644 --- a/src/core/execution/TradeShipExecution.ts +++ b/src/core/execution/TradeShipExecution.ts @@ -8,7 +8,6 @@ import { UnitType, } from "../game/Game"; import { TileRef } from "../game/GameMap"; -import { MotionPlanRecord } from "../game/MotionPlans"; import { PathFinding } from "../pathfinding/PathFinder"; import { PathStatus, SteppingPathFinder } from "../pathfinding/types"; import { distSortUnit } from "../Util"; @@ -35,7 +34,6 @@ export class TradeShipExecution implements Execution { } tick(ticks: number): void { - let spawnedThisTick = false; if (this.tradeShip === undefined) { const spawn = this.origOwner.canBuild( UnitType.TradeShip, @@ -50,19 +48,10 @@ export class TradeShipExecution implements Execution { targetUnit: this._dstPort, lastSetSafeFromPirates: ticks, }); + // This unit can move immediately, but plan-driven units don't emit per-step Unit updates. + // Mark it plan-driven up-front so its first move doesn't generate redundant traffic. + this.mg.markUnitPlanDriven(this.tradeShip.id()); this.mg.stats().boatSendTrade(this.origOwner, this._dstPort.owner()); - spawnedThisTick = true; - - const placeholderPlan: MotionPlanRecord = { - kind: "grid", - unitId: this.tradeShip.id(), - planId: this.motionPlanId, - startTick: ticks + 1, - ticksPerStep: 1, - path: [spawn], - }; - this.mg.recordMotionPlan(placeholderPlan); - this.motionPlanDst = this._dstPort.tile(); } if (!this.tradeShip.isActive()) { @@ -146,7 +135,7 @@ export class TradeShipExecution implements Execution { } const dst = this._dstPort.tile(); - if (spawnedThisTick || dst !== this.motionPlanDst) { + if (dst !== this.motionPlanDst) { this.motionPlanId++; const from = this.tradeShip.tile(); const path = this.pathFinder.findPath(from, dst) ?? [from]; diff --git a/src/core/execution/TransportShipExecution.ts b/src/core/execution/TransportShipExecution.ts index 2dabad56d..061811c34 100644 --- a/src/core/execution/TransportShipExecution.ts +++ b/src/core/execution/TransportShipExecution.ts @@ -277,7 +277,7 @@ export class TransportShipExecution implements Execution { kind: "grid", unitId: this.boat.id(), planId: this.motionPlanId, - startTick: ticks + 1, + startTick: ticks + this.ticksPerMove, ticksPerStep: this.ticksPerMove, path: fullPath, }); diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index c44705d37..206a761be 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -778,6 +778,11 @@ export interface Game extends GameMap { inSpawnPhase(): boolean; executeNextTick(): GameUpdates; drainPackedTileUpdates(): Uint32Array; + /** + * Marks a unit as "plan-driven" so its per-tile `Unit` updates can be suppressed. + * The client is expected to advance the unit position via motion plans. + */ + markUnitPlanDriven(unitId: number): void; recordMotionPlan(record: MotionPlanRecord): void; drainPackedMotionPlans(): Uint32Array | null; setWinner(winner: Player | Team, allPlayersStats: AllPlayersStats): void; diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index 267ff7e04..654567892 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -447,6 +447,10 @@ export class GameImpl implements Game { return packed; } + markUnitPlanDriven(unitId: number): void { + this.planDrivenUnitIds.add(unitId); + } + recordMotionPlan(record: MotionPlanRecord): void { switch (record.kind) { case "grid":