forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
6114a2295f
commit
69809f7228
593 files changed
+903643
-40774
No files matched your search
@@ -0,0 +1,79 @@
|
||||
// This self-contained factory also runs in the browser's QA context. It only
|
||||
// subscribes to committed state; it never writes the game stores.
|
||||
function createWeaponEvidenceRecorder(store, options = {}) {
|
||||
const capacity = options.capacity ?? 50_000;
|
||||
const clock = options.clock ?? Date.now;
|
||||
const initial = store.getState();
|
||||
const baselineEventId = initial.combatEvents?.at(-1)?.id ?? 0;
|
||||
let lastEventId = baselineEventId;
|
||||
let stopped = false;
|
||||
const events = [], gaps = [], mobSamples = [], auraSamples = [], errors = [];
|
||||
const signatures = new Map();
|
||||
let auraSignature = null;
|
||||
let discardedEvents = 0, discardedStates = 0;
|
||||
const retain = (array, entry, event = false) => {
|
||||
if (array.length < capacity) array.push(entry);
|
||||
else if (event) discardedEvents += 1;
|
||||
else discardedStates += 1;
|
||||
};
|
||||
const observe = (state) => {
|
||||
if (stopped) return;
|
||||
try {
|
||||
const fresh = (state.combatEvents ?? []).filter((event) => event.id > lastEventId);
|
||||
for (const event of fresh) {
|
||||
if (event.id > lastEventId + 1) gaps.push({ afterId: lastEventId, beforeId: event.id });
|
||||
retain(events, { ...event }, true);
|
||||
lastEventId = event.id;
|
||||
}
|
||||
const observedAt = clock();
|
||||
for (const mob of Object.values(state.mobs ?? {})) {
|
||||
const entry = {
|
||||
id: mob.id, name: mob.name, serverEntry: mob.serverEntry ?? null,
|
||||
sourceCreatureGuid: mob.sourceCreatureGuid ?? null,
|
||||
sourceEquipment: mob.sourceEquipment ? JSON.parse(JSON.stringify(mob.sourceEquipment)) : null,
|
||||
engaged: Boolean(mob.engaged), dead: Boolean(mob.dead),
|
||||
dualWieldEnabled: mob.dualWieldEnabled ?? null,
|
||||
nextEnemyOffhandAttackAt: mob.nextEnemyOffhandAttackAt ?? null,
|
||||
pendingExtraAttacks: mob.pendingExtraAttacks?.map((queued) => ({ ...queued })) ?? null,
|
||||
lastDamagedActorId: mob.lastDamagedActorId ?? null,
|
||||
};
|
||||
const signature = JSON.stringify(entry);
|
||||
if (signatures.get(mob.id) !== signature) {
|
||||
signatures.set(mob.id, signature);
|
||||
retain(mobSamples, { observedAt, ...entry });
|
||||
}
|
||||
}
|
||||
const active = (state.auras ?? []).filter((aura) =>
|
||||
/^(?:enemy-source-spell-(?:6742|6713|17230|3419)|enemy-control:source-spell-(?:5246|19134|20511|29544))$/.test(aura.definition?.id ?? '')).map((aura) => ({
|
||||
instanceId: aura.instanceId, definitionId: aura.definition.id,
|
||||
sourceId: aura.sourceId, targetId: aura.targetId,
|
||||
appliedAt: aura.appliedAt, expiresAt: aura.expiresAt, stacks: aura.stacks,
|
||||
dispelCategory: aura.definition.dispelCategory ?? null,
|
||||
}));
|
||||
const nextAuraSignature = JSON.stringify(active);
|
||||
if (nextAuraSignature !== auraSignature) {
|
||||
auraSignature = nextAuraSignature;
|
||||
retain(auraSamples, { observedAt, auras: active });
|
||||
}
|
||||
} catch (error) {
|
||||
if (errors.length < 10) errors.push(String(error?.message ?? error));
|
||||
}
|
||||
};
|
||||
observe(initial);
|
||||
const unsubscribe = store.subscribe(observe);
|
||||
return {
|
||||
stop() {
|
||||
if (!stopped) {
|
||||
observe(store.getState());
|
||||
stopped = true;
|
||||
unsubscribe();
|
||||
}
|
||||
return { baselineEventId, lastEventId, events, gaps, mobSamples, auraSamples,
|
||||
discardedEvents, discardedStates, errors,
|
||||
eventCoverage: 'Committed-store subscription with event-ID gap auditing; pre-start events excluded.',
|
||||
stateCoverage: 'Weapon and source-aura changes at store commits, including combat between route checkpoints.' };
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { createWeaponEvidenceRecorder };
|
||||
Reference in new issue
Block a user