mirror of
https://github.com/Shu-Ying/noname-shuying.git
synced 2026-10-06 00:28:09 +08:00
56 lines
3.0 KiB
JavaScript
56 lines
3.0 KiB
JavaScript
// Exclusive battle resources. Never clear arbitrary global queues or arbitrary timers.
|
|
export function createBattleResources(session, {game, ui, _status}) {
|
|
const cards = new Set(), nodes = new Map(), fields = [];
|
|
const containers = () => [ui.arena, ui.control, ui.sidebar, ui.cardPile, ui.discardPile, ui.ordering, ui.special].filter(Boolean);
|
|
const children = () => new Map(containers().map(parent => [parent, new Set(parent.childNodes)]));
|
|
const before = children();
|
|
const uiKeys = ["me","handcards1Container","handcards2Container","handcards1","handcards2"];
|
|
const uiBefore = new Map(uiKeys.map(key => [key,Object.getOwnPropertyDescriptor(ui,key)]));
|
|
function field(object, key, value) {
|
|
const descriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
object[key] = value;
|
|
fields.push({object,key,value,descriptor});
|
|
return value;
|
|
}
|
|
// Install before root.start so global history cannot retain the finished battle tree.
|
|
field(_status, "globalHistory", [{cardMove:[],custom:[],useCard:[],changeHp:[],everything:[]}]);
|
|
field(_status, "cardtag", Object.fromEntries(Object.keys(_status.cardtag || {}).map(key => [key,[]])));
|
|
const counters = {phaseNumber:game.phaseNumber, roundNumber:game.roundNumber};
|
|
game.phaseNumber = 0; game.roundNumber = 0;
|
|
session.ownResource({}, () => {
|
|
for (const card of cards) card.remove();
|
|
for (const [node,parent] of nodes) if (node.parentNode === parent) node.remove();
|
|
for (const {object,key,value,descriptor} of fields.reverse()) {
|
|
if (object[key] !== value) continue; // A replacement owned by another subsystem survives.
|
|
if (descriptor) Object.defineProperty(object,key,descriptor); else delete object[key];
|
|
}
|
|
game.phaseNumber = counters.phaseNumber; game.roundNumber = counters.roundNumber;
|
|
});
|
|
return Object.freeze({
|
|
field,
|
|
card(card) { cards.add(card); return card; },
|
|
capturePreparedArena() {
|
|
for (const key of uiKeys) {
|
|
const descriptor = uiBefore.get(key);
|
|
if (ui[key] !== descriptor?.value) fields.push({object:ui,key,value:ui[key],descriptor});
|
|
}
|
|
// Call synchronously after prepareArena, with onfree already drained.
|
|
for (const parent of containers()) {
|
|
const prior = before.get(parent) || new Set();
|
|
for (const node of parent.childNodes) if (!prior.has(node)) {
|
|
if ([ui.cardPile,ui.discardPile,ui.ordering,ui.special].includes(parent)) cards.add(node);
|
|
else nodes.set(node,parent);
|
|
}
|
|
}
|
|
},
|
|
bindPlayers(players) {
|
|
const owned = new Set(players);
|
|
session.ownResource({}, () => {
|
|
for (const key of ["currentPhase","lastPhasedPlayer","roundStart"]) {
|
|
if (owned.has(_status[key])) delete _status[key];
|
|
}
|
|
});
|
|
},
|
|
});
|
|
}
|