Files
OpenFrontIO/src/core/execution/ExecutionManager.ts
T
2026-02-11 18:32:27 +09:00

149 lines
5.4 KiB
TypeScript

import { Execution, Game } from "../game/Game";
import { PseudoRandom } from "../PseudoRandom";
import { ClientID, GameID, StampedIntent, Turn } from "../Schemas";
import { simpleHash } from "../Util";
import { AllianceExtensionExecution } from "./alliance/AllianceExtensionExecution";
import { AllianceRequestExecution } from "./alliance/AllianceRequestExecution";
import { AllianceRequestReplyExecution } from "./alliance/AllianceRequestReplyExecution";
import { BreakAllianceExecution } from "./alliance/BreakAllianceExecution";
import { AttackExecution } from "./AttackExecution";
import { BoatRetreatExecution } from "./BoatRetreatExecution";
import { BotSpawner } from "./BotSpawner";
import { ConstructionExecution } from "./ConstructionExecution";
import { DeleteUnitExecution } from "./DeleteUnitExecution";
import { DonateGoldExecution } from "./DonateGoldExecution";
import { DonateTroopsExecution } from "./DonateTroopExecution";
import { EmbargoAllExecution } from "./EmbargoAllExecution";
import { EmbargoExecution } from "./EmbargoExecution";
import { EmojiExecution } from "./EmojiExecution";
import { MarkDisconnectedExecution } from "./MarkDisconnectedExecution";
import { MoveWarshipExecution } from "./MoveWarshipExecution";
import { NationExecution } from "./NationExecution";
import { NoOpExecution } from "./NoOpExecution";
import { PauseExecution } from "./PauseExecution";
import { QuickChatExecution } from "./QuickChatExecution";
import { RetreatExecution } from "./RetreatExecution";
import { SpawnExecution } from "./SpawnExecution";
import { TargetPlayerExecution } from "./TargetPlayerExecution";
import { TransportShipExecution } from "./TransportShipExecution";
import { UpgradeStructureExecution } from "./UpgradeStructureExecution";
import { PlayerSpawner } from "./utils/PlayerSpawner";
export class Executor {
// private random = new PseudoRandom(999)
private random: PseudoRandom;
constructor(
private mg: Game,
private gameID: GameID,
private clientID: ClientID,
) {
// Add one to avoid id collisions with bots.
this.random = new PseudoRandom(simpleHash(gameID) + 1);
}
createExecs(turn: Turn): Execution[] {
return turn.intents.map((i) => this.createExec(i));
}
createExec(intent: StampedIntent): Execution {
const player = this.mg.playerByClientID(intent.clientID);
if (!player) {
console.warn(`player with clientID ${intent.clientID} not found`);
return new NoOpExecution();
}
// create execution
switch (intent.type) {
case "attack": {
return new AttackExecution(
intent.troops,
player,
intent.targetID,
intent.sourceTile ?? null,
);
}
case "cancel_attack":
return new RetreatExecution(player, intent.attackID);
case "cancel_boat":
return new BoatRetreatExecution(player, intent.unitID);
case "move_warship":
return new MoveWarshipExecution(player, intent.unitId, intent.tile);
case "spawn":
return new SpawnExecution(this.gameID, player.info(), intent.tile);
case "boat":
return new TransportShipExecution(player, intent.dst, intent.troops);
case "allianceRequest":
return new AllianceRequestExecution(player, intent.recipient);
case "allianceRequestReply":
return new AllianceRequestReplyExecution(
intent.requestor,
player,
intent.accept,
);
case "breakAlliance":
return new BreakAllianceExecution(player, intent.recipient);
case "targetPlayer":
return new TargetPlayerExecution(player, intent.target);
case "emoji":
return new EmojiExecution(player, intent.recipient, intent.emoji);
case "donate_troops":
return new DonateTroopsExecution(
player,
intent.recipient,
intent.troops,
);
case "donate_gold":
return new DonateGoldExecution(player, intent.recipient, intent.gold);
case "embargo":
return new EmbargoExecution(player, intent.targetID, intent.action);
case "embargo_all":
return new EmbargoAllExecution(player, intent.action);
case "build_unit":
return new ConstructionExecution(
player,
intent.unit,
intent.tile,
intent.rocketDirectionUp,
);
case "allianceExtension": {
return new AllianceExtensionExecution(player, intent.recipient);
}
case "upgrade_structure":
return new UpgradeStructureExecution(player, intent.unitId);
case "delete_unit":
return new DeleteUnitExecution(player, intent.unitId);
case "quick_chat":
return new QuickChatExecution(
player,
intent.recipient,
intent.quickChatKey,
intent.target,
);
case "mark_disconnected":
return new MarkDisconnectedExecution(player, intent.isDisconnected);
case "toggle_pause":
return new PauseExecution(player, intent.paused);
default:
throw new Error(`intent type ${intent} not found`);
}
}
spawnBots(numBots: number): SpawnExecution[] {
return new BotSpawner(this.mg, this.gameID).spawnBots(numBots);
}
spawnPlayers(): SpawnExecution[] {
return new PlayerSpawner(this.mg, this.gameID).spawnPlayers();
}
nationExecutions(): Execution[] {
const execs: Execution[] = [];
for (const nation of this.mg.nations()) {
execs.push(new NationExecution(this.gameID, nation));
}
return execs;
}
}