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"
|
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||||
}, {
|
}, {
|
||||||
"url": "index.html",
|
"url": "index.html",
|
||||||
"revision": "0.vopjl6fp8f"
|
"revision": "0.inrr5fp7a9"
|
||||||
}], {});
|
}], {});
|
||||||
workbox.cleanupOutdatedCaches();
|
workbox.cleanupOutdatedCaches();
|
||||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||||
|
|||||||
@@ -706,6 +706,14 @@ export const GameView: React.FC<GameViewProps> = ({ gameState, currentPlayerId }
|
|||||||
onDragStart={() => { }}
|
onDragStart={() => { }}
|
||||||
onClick={(id) => {
|
onClick={(id) => {
|
||||||
if (gameState.step === 'declare_attackers') {
|
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);
|
const newSet = new Set(proposedAttackers);
|
||||||
if (newSet.has(id)) newSet.delete(id);
|
if (newSet.has(id)) newSet.delete(id);
|
||||||
else newSet.add(id);
|
else newSet.add(id);
|
||||||
|
|||||||
@@ -471,14 +471,25 @@ export class RulesEngine {
|
|||||||
// 4. Combat Steps requiring declaration (Pause for External Action)
|
// 4. Combat Steps requiring declaration (Pause for External Action)
|
||||||
if (step === 'declare_attackers') {
|
if (step === 'declare_attackers') {
|
||||||
// WAITING for declareAttackers() from Client
|
// WAITING for declareAttackers() from Client
|
||||||
// Do NOT reset priority yet.
|
// 508.1. Active Player gets priority to declare attackers.
|
||||||
// TODO: Maybe set a timeout or auto-skip if no creatures?
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step === 'declare_blockers') {
|
if (step === 'declare_blockers') {
|
||||||
// WAITING for declareBlockers() from Client (Defending Player)
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,12 @@ export class GameManager {
|
|||||||
engine.castSpell(actorId, action.cardId, action.targets, action.position);
|
engine.castSpell(actorId, action.cardId, action.targets, action.position);
|
||||||
break;
|
break;
|
||||||
case 'DECLARE_ATTACKERS':
|
case 'DECLARE_ATTACKERS':
|
||||||
|
try {
|
||||||
engine.declareAttackers(actorId, action.attackers);
|
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;
|
break;
|
||||||
case 'DECLARE_BLOCKERS':
|
case 'DECLARE_BLOCKERS':
|
||||||
engine.declareBlockers(actorId, action.blockers);
|
engine.declareBlockers(actorId, action.blockers);
|
||||||
|
|||||||
Reference in New Issue
Block a user