diff --git a/src/client/Transport.ts b/src/client/Transport.ts index 0e7a07030..c4fd5f700 100644 --- a/src/client/Transport.ts +++ b/src/client/Transport.ts @@ -308,7 +308,7 @@ export class Transport { this.sendIntent({ type: "allianceRequest", clientID: this.lobbyConfig.clientID, - requestor: event.requestor.id(), + playerID: event.requestor.id(), recipient: event.recipient.id(), }); } @@ -318,7 +318,7 @@ export class Transport { type: "allianceRequestReply", clientID: this.lobbyConfig.clientID, requestor: event.requestor.id(), - recipient: event.recipient.id(), + playerID: event.recipient.id(), accept: event.accepted, }); } @@ -327,7 +327,7 @@ export class Transport { this.sendIntent({ type: "breakAlliance", clientID: this.lobbyConfig.clientID, - requestor: event.requestor.id(), + playerID: event.requestor.id(), recipient: event.recipient.id(), }); } @@ -349,7 +349,7 @@ export class Transport { this.sendIntent({ type: "attack", clientID: this.lobbyConfig.clientID, - attackerID: this.lobbyConfig.playerID, + playerID: this.lobbyConfig.playerID, targetID: event.targetID, troops: event.troops, }); @@ -359,7 +359,7 @@ export class Transport { this.sendIntent({ type: "boat", clientID: this.lobbyConfig.clientID, - attackerID: this.lobbyConfig.playerID, + playerID: this.lobbyConfig.playerID, targetID: event.targetID, troops: event.troops, x: event.cell.x, @@ -371,7 +371,7 @@ export class Transport { this.sendIntent({ type: "targetPlayer", clientID: this.lobbyConfig.clientID, - requestor: this.lobbyConfig.playerID, + playerID: this.lobbyConfig.playerID, target: event.targetID, }); } @@ -380,7 +380,7 @@ export class Transport { this.sendIntent({ type: "emoji", clientID: this.lobbyConfig.clientID, - sender: this.lobbyConfig.playerID, + playerID: this.lobbyConfig.playerID, recipient: event.recipient == AllPlayers ? AllPlayers : event.recipient.id(), emoji: event.emoji, @@ -391,7 +391,7 @@ export class Transport { this.sendIntent({ type: "donate", clientID: this.lobbyConfig.clientID, - sender: event.sender.id(), + playerID: event.sender.id(), recipient: event.recipient.id(), troops: event.troops, }); @@ -401,7 +401,7 @@ export class Transport { this.sendIntent({ type: "troop_ratio", clientID: this.lobbyConfig.clientID, - player: this.lobbyConfig.playerID, + playerID: this.lobbyConfig.playerID, ratio: event.ratio, }); } @@ -410,7 +410,7 @@ export class Transport { this.sendIntent({ type: "build_unit", clientID: this.lobbyConfig.clientID, - player: this.lobbyConfig.playerID, + playerID: this.lobbyConfig.playerID, unit: event.unit, x: event.cell.x, y: event.cell.y, diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts index f8796c725..eb81c6698 100644 --- a/src/core/Schemas.ts +++ b/src/core/Schemas.ts @@ -133,11 +133,12 @@ const BaseIntentSchema = z.object({ "build_unit", ]), clientID: ID, + playerID: ID, }); export const AttackIntentSchema = BaseIntentSchema.extend({ type: z.literal("attack"), - attackerID: ID, + playerID: ID, targetID: ID.nullable(), troops: z.number().nullable(), }); @@ -154,7 +155,7 @@ export const SpawnIntentSchema = BaseIntentSchema.extend({ export const BoatAttackIntentSchema = BaseIntentSchema.extend({ type: z.literal("boat"), - attackerID: ID, + playerID: ID, targetID: ID.nullable(), troops: z.number().nullable(), x: z.number(), @@ -163,52 +164,52 @@ export const BoatAttackIntentSchema = BaseIntentSchema.extend({ export const AllianceRequestIntentSchema = BaseIntentSchema.extend({ type: z.literal("allianceRequest"), - requestor: ID, + playerID: ID, recipient: ID, }); export const AllianceRequestReplyIntentSchema = BaseIntentSchema.extend({ type: z.literal("allianceRequestReply"), requestor: ID, // The one who made the original alliance request - recipient: ID, + playerID: ID, accept: z.boolean(), }); export const BreakAllianceIntentSchema = BaseIntentSchema.extend({ type: z.literal("breakAlliance"), - requestor: ID, // The one who made the original alliance request + playerID: ID, recipient: ID, }); export const TargetPlayerIntentSchema = BaseIntentSchema.extend({ type: z.literal("targetPlayer"), - requestor: ID, + playerID: ID, target: ID, }); export const EmojiIntentSchema = BaseIntentSchema.extend({ type: z.literal("emoji"), - sender: ID, + playerID: ID, recipient: z.union([ID, z.literal(AllPlayers)]), emoji: EmojiSchema, }); export const DonateIntentSchema = BaseIntentSchema.extend({ type: z.literal("donate"), - sender: ID, + playerID: ID, recipient: ID, troops: z.number().nullable(), }); export const TargetTroopRatioIntentSchema = BaseIntentSchema.extend({ type: z.literal("troop_ratio"), - player: ID, + playerID: ID, ratio: z.number().min(0).max(1), }); export const BuildUnitIntentSchema = BaseIntentSchema.extend({ type: z.literal("build_unit"), - player: ID, + playerID: ID, unit: z.nativeEnum(UnitType), x: z.number(), y: z.number(), diff --git a/src/core/execution/ExecutionManager.ts b/src/core/execution/ExecutionManager.ts index b7e3f2c92..e876c9cac 100644 --- a/src/core/execution/ExecutionManager.ts +++ b/src/core/execution/ExecutionManager.ts @@ -33,6 +33,7 @@ import { DonateExecution } from "./DonateExecution"; import { SetTargetTroopRatioExecution } from "./SetTargetTroopRatioExecution"; import { ConstructionExecution } from "./ConstructionExecution"; import { fixProfaneUsername, isProfaneUsername } from "../validations/username"; +import { NoOpExecution } from "./NoOpExecution"; export class Executor { // private random = new PseudoRandom(999) @@ -52,11 +53,26 @@ export class Executor { } createExec(intent: Intent): Execution { + if (intent.type != "spawn") { + if (!this.mg.hasPlayer(intent.playerID)) { + console.warn( + `player ${intent.playerID} not found on intent ${intent.type}`, + ); + return new NoOpExecution(); + } + const player = this.mg.player(intent.playerID); + if (player.clientID() != intent.clientID) { + console.warn( + `intent ${intent.type} has incorrect clientID ${intent.clientID} for player ${player.name()} with clientID ${player.clientID()}`, + ); + return new NoOpExecution(); + } + } switch (intent.type) { case "attack": { return new AttackExecution( intent.troops, - intent.attackerID, + intent.playerID, intent.targetID, null, ); @@ -77,40 +93,40 @@ export class Executor { ); case "boat": return new TransportShipExecution( - intent.attackerID, + intent.playerID, intent.targetID, this.mg.ref(intent.x, intent.y), intent.troops, ); case "allianceRequest": - return new AllianceRequestExecution(intent.requestor, intent.recipient); + return new AllianceRequestExecution(intent.playerID, intent.recipient); case "allianceRequestReply": return new AllianceRequestReplyExecution( intent.requestor, - intent.recipient, + intent.playerID, intent.accept, ); case "breakAlliance": - return new BreakAllianceExecution(intent.requestor, intent.recipient); + return new BreakAllianceExecution(intent.playerID, intent.recipient); case "targetPlayer": - return new TargetPlayerExecution(intent.requestor, intent.target); + return new TargetPlayerExecution(intent.playerID, intent.target); case "emoji": return new EmojiExecution( - intent.sender, + intent.playerID, intent.recipient, intent.emoji, ); case "donate": return new DonateExecution( - intent.sender, + intent.playerID, intent.recipient, intent.troops, ); case "troop_ratio": - return new SetTargetTroopRatioExecution(intent.player, intent.ratio); + return new SetTargetTroopRatioExecution(intent.playerID, intent.ratio); case "build_unit": return new ConstructionExecution( - intent.player, + intent.playerID, this.mg.ref(intent.x, intent.y), intent.unit, ); diff --git a/src/core/execution/MIRVExecution.ts b/src/core/execution/MIRVExecution.ts index f865eea75..87638fe7b 100644 --- a/src/core/execution/MIRVExecution.ts +++ b/src/core/execution/MIRVExecution.ts @@ -43,7 +43,7 @@ export class MirvExecution implements Execution { ) {} init(mg: Game, ticks: number): void { - if (!this.mg.hasPlayer(this.senderID)) { + if (!mg.hasPlayer(this.senderID)) { console.warn(`MIRVExecution: player ${this.senderID} not found`); this.active = false; return; diff --git a/src/core/execution/NoOpExecution.ts b/src/core/execution/NoOpExecution.ts new file mode 100644 index 000000000..eefce20ed --- /dev/null +++ b/src/core/execution/NoOpExecution.ts @@ -0,0 +1,15 @@ +import { Execution, Game, Player } from "../game/Game"; + +export class NoOpExecution implements Execution { + isActive(): boolean { + return false; + } + activeDuringSpawnPhase(): boolean { + return false; + } + init(mg: Game, ticks: number): void {} + tick(ticks: number): void {} + owner(): Player { + return null; + } +} diff --git a/src/core/execution/alliance/AllianceRequestExecution.ts b/src/core/execution/alliance/AllianceRequestExecution.ts index c5a20843a..21128d840 100644 --- a/src/core/execution/alliance/AllianceRequestExecution.ts +++ b/src/core/execution/alliance/AllianceRequestExecution.ts @@ -19,6 +19,21 @@ export class AllianceRequestExecution implements Execution { ) {} init(mg: Game, ticks: number): void { + if (!mg.hasPlayer(this.requestorID)) { + console.warn( + `AllianceRequestExecution requester ${this.requestorID} not found`, + ); + this.active = false; + return; + } + if (!mg.hasPlayer(this.recipientID)) { + console.warn( + `AllianceRequestExecution recipient ${this.recipientID} not found`, + ); + this.active = false; + return; + } + this.mg = mg; this.requestor = mg.player(this.requestorID); this.recipient = mg.player(this.recipientID); diff --git a/src/core/execution/alliance/AllianceRequestReplyExecution.ts b/src/core/execution/alliance/AllianceRequestReplyExecution.ts index 4250d476a..d0c0d4688 100644 --- a/src/core/execution/alliance/AllianceRequestReplyExecution.ts +++ b/src/core/execution/alliance/AllianceRequestReplyExecution.ts @@ -20,6 +20,20 @@ export class AllianceRequestReplyExecution implements Execution { ) {} init(mg: Game, ticks: number): void { + if (!mg.hasPlayer(this.requestorID)) { + console.warn( + `AllianceRequestReplyExecution requester ${this.requestorID} not found`, + ); + this.active = false; + return; + } + if (!mg.hasPlayer(this.recipientID)) { + console.warn( + `AllianceRequestReplyExecution recipient ${this.recipientID} not found`, + ); + this.active = false; + return; + } this.mg = mg; this.requestor = mg.player(this.requestorID); this.recipient = mg.player(this.recipientID); diff --git a/src/core/execution/alliance/BreakAllianceExecution.ts b/src/core/execution/alliance/BreakAllianceExecution.ts index 2beff3d8a..074e72ab7 100644 --- a/src/core/execution/alliance/BreakAllianceExecution.ts +++ b/src/core/execution/alliance/BreakAllianceExecution.ts @@ -19,6 +19,20 @@ export class BreakAllianceExecution implements Execution { ) {} init(mg: Game, ticks: number): void { + if (!mg.hasPlayer(this.requestorID)) { + console.warn( + `BreakAllianceExecution requester ${this.requestorID} not found`, + ); + this.active = false; + return; + } + if (!mg.hasPlayer(this.recipientID)) { + console.warn( + `BreakAllianceExecution: recipient ${this.recipientID} not found`, + ); + this.active = false; + return; + } this.requestor = mg.player(this.requestorID); this.recipient = mg.player(this.recipientID); this.mg = mg;