feat: Improve attacker/blocker declaration by adding client-side creature validation, enforcing correct player priority, and enhancing server-side error logging.
This commit is contained in:
@@ -82,7 +82,7 @@ define(['./workbox-5a5d9309'], (function (workbox) { 'use strict';
|
||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||
}, {
|
||||
"url": "index.html",
|
||||
"revision": "0.vopjl6fp8f"
|
||||
"revision": "0.inrr5fp7a9"
|
||||
}], {});
|
||||
workbox.cleanupOutdatedCaches();
|
||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||
|
||||
@@ -706,6 +706,14 @@ export const GameView: React.FC<GameViewProps> = ({ gameState, currentPlayerId }
|
||||
onDragStart={() => { }}
|
||||
onClick={(id) => {
|
||||
if (gameState.step === 'declare_attackers') {
|
||||
// Validate Creature Type
|
||||
const types = card.types || [];
|
||||
const typeLine = card.typeLine || '';
|
||||
if (!types.includes('Creature') && !typeLine.includes('Creature')) {
|
||||
// Optional: Shake effect or visual feedback that it's invalid
|
||||
return;
|
||||
}
|
||||
|
||||
const newSet = new Set(proposedAttackers);
|
||||
if (newSet.has(id)) newSet.delete(id);
|
||||
else newSet.add(id);
|
||||
|
||||
@@ -471,14 +471,25 @@ export class RulesEngine {
|
||||
// 4. Combat Steps requiring declaration (Pause for External Action)
|
||||
if (step === 'declare_attackers') {
|
||||
// WAITING for declareAttackers() from Client
|
||||
// Do NOT reset priority yet.
|
||||
// TODO: Maybe set a timeout or auto-skip if no creatures?
|
||||
// 508.1. Active Player gets priority to declare attackers.
|
||||
// Unlike other steps where AP gets priority to cast spells, here the "Action" determines the flow.
|
||||
// But technically, the AP *must* act. So we ensure they have priority.
|
||||
if (this.state.priorityPlayerId !== activePlayerId) {
|
||||
this.resetPriority(activePlayerId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (step === 'declare_blockers') {
|
||||
// WAITING for declareBlockers() from Client (Defending Player)
|
||||
// Do NOT reset priority yet.
|
||||
// 509.1. Defending Player gets priority to declare blockers.
|
||||
// In 1v1, this is the non-active player.
|
||||
const defendingPlayerId = this.state.turnOrder.find(id => id !== activePlayerId);
|
||||
if (defendingPlayerId) {
|
||||
if (this.state.priorityPlayerId !== defendingPlayerId) {
|
||||
this.resetPriority(defendingPlayerId);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,12 @@ export class GameManager {
|
||||
engine.castSpell(actorId, action.cardId, action.targets, action.position);
|
||||
break;
|
||||
case 'DECLARE_ATTACKERS':
|
||||
engine.declareAttackers(actorId, action.attackers);
|
||||
try {
|
||||
engine.declareAttackers(actorId, action.attackers);
|
||||
} catch (err: any) {
|
||||
console.error(`[DeclareAttackers Error] Actor: ${actorId}, Active: ${game.activePlayerId}, Priority: ${game.priorityPlayerId}, Step: ${game.step}`);
|
||||
throw err; // Re-throw to catch block below
|
||||
}
|
||||
break;
|
||||
case 'DECLARE_BLOCKERS':
|
||||
engine.declareBlockers(actorId, action.blockers);
|
||||
|
||||
Reference in New Issue
Block a user