Fix combat loop: blacklist entities for 30s after engagement

The core problem: attacks don't deal damage (protocol issue), so
mobs never die. entityGone fires spuriously, combat "ends", then
the 2-second scan finds the same mob and re-engages endlessly.

Fix: after combat ends for ANY reason, the entity ID is blacklisted
for 30 seconds. The scan loop skips blacklisted entities. This
prevents the infinite re-engage loop.

The underlying damage issue still needs investigation, but at least
Doug won't get stuck in an endless combat loop anymore.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
roberts 2026-03-30 20:36:05 -05:00
parent 9869181071
commit 7363e8589f

View file

@ -262,6 +262,8 @@ let combatActive = false;
let combatTargetId = null; let combatTargetId = null;
let combatInterval = null; let combatInterval = null;
let lastEquipCheck = 0; let lastEquipCheck = 0;
const combatBlacklist = new Map(); // entityId → timestamp (don't re-engage)
const COMBAT_BLACKLIST_DURATION = 30000; // 30 seconds
function startCombat(target) { function startCombat(target) {
if (combatActive) return; if (combatActive) return;
@ -321,7 +323,11 @@ function endCombat(reason) {
if (combatInterval) clearInterval(combatInterval); if (combatInterval) clearInterval(combatInterval);
combatInterval = null; combatInterval = null;
combatActive = false; combatActive = false;
log('client', 'INFO', `⚔ Combat ended: ${reason}`); // Blacklist this entity so we don't re-engage immediately
if (combatTargetId != null) {
combatBlacklist.set(combatTargetId, Date.now());
}
log('client', 'INFO', `Combat ended: ${reason} (blacklisted for 30s)`);
sendEvent('combat_ended', { reason }); sendEvent('combat_ended', { reason });
combatTargetId = null; combatTargetId = null;
} }
@ -330,6 +336,12 @@ function endCombat(reason) {
setInterval(() => { setInterval(() => {
if (!spawned || combatActive) return; if (!spawned || combatActive) return;
// Clean expired blacklist entries
const now = Date.now();
for (const [id, time] of combatBlacklist) {
if (now - time > COMBAT_BLACKLIST_DURATION) combatBlacklist.delete(id);
}
const pos = bot.entity.position; const pos = bot.entity.position;
let closestHostile = null; let closestHostile = null;
let closestDist = 8; // Aggro range let closestDist = 8; // Aggro range
@ -337,6 +349,8 @@ setInterval(() => {
for (const entity of Object.values(bot.entities)) { for (const entity of Object.values(bot.entities)) {
if (entity === bot.entity || !entity.position) continue; if (entity === bot.entity || !entity.position) continue;
if (!isHostile(entity)) continue; if (!isHostile(entity)) continue;
// Skip blacklisted entities (already fought, didn't die)
if (combatBlacklist.has(entity.id)) continue;
const dist = entity.position.distanceTo(pos); const dist = entity.position.distanceTo(pos);
if (dist < closestDist) { if (dist < closestDist) {
closestDist = dist; closestDist = dist;