Add HYTALE_PATCH_SKIP to skip specific occurrences by index

HYTALE_PATCH_SKIP=0 - skip first occurrence only
HYTALE_PATCH_SKIP=0,2 - skip first and third
HYTALE_PATCH_SKIP=0 HYTALE_PATCH_LIMIT=1 - patch only second occurrence

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
sanasol
2026-01-27 03:38:09 +01:00
parent aab67e8e28
commit 654deca933

View File

@@ -185,7 +185,9 @@ class ClientPatcher {
} }
/** /**
* Replace bytes with a limit on number of occurrences (for debugging) * Replace bytes with skip/limit control (for debugging)
* HYTALE_PATCH_SKIP: comma-separated indices to skip (e.g., "0,2" skips 1st and 3rd)
* HYTALE_PATCH_LIMIT: max number of patches to apply
*/ */
replaceBytesLimited(buffer, oldBytes, newBytes, limit) { replaceBytesLimited(buffer, oldBytes, newBytes, limit) {
let count = 0; let count = 0;
@@ -196,18 +198,36 @@ class ClientPatcher {
return { buffer: result, count: 0 }; return { buffer: result, count: 0 };
} }
// Parse skip list from env
const skipIndices = (process.env.HYTALE_PATCH_SKIP || '')
.split(',')
.filter(s => s.trim())
.map(s => parseInt(s.trim(), 10));
if (skipIndices.length > 0) {
console.log(` Skip indices: ${skipIndices.join(', ')}`);
}
const positions = this.findAllOccurrences(result, oldBytes); const positions = this.findAllOccurrences(result, oldBytes);
for (const pos of positions) { let patchedCount = 0;
if (count >= limit) { for (let i = 0; i < positions.length; i++) {
console.log(` Skipping offset 0x${pos.toString(16)} (limit reached)`); const pos = positions[i];
continue;
}
// Log offset and surrounding bytes for debugging // Log offset and surrounding bytes for debugging
const before = result.slice(Math.max(0, pos - 8), pos); const before = result.slice(Math.max(0, pos - 8), pos);
const after = result.slice(pos + oldBytes.length, Math.min(result.length, pos + oldBytes.length + 8)); const after = result.slice(pos + oldBytes.length, Math.min(result.length, pos + oldBytes.length + 8));
console.log(` Patching at offset 0x${pos.toString(16)} (${pos})`);
if (skipIndices.includes(i)) {
console.log(` [${i}] Skipping offset 0x${pos.toString(16)} (in skip list)`);
continue;
}
if (patchedCount >= limit) {
console.log(` [${i}] Skipping offset 0x${pos.toString(16)} (limit reached)`);
continue;
}
console.log(` [${i}] Patching at offset 0x${pos.toString(16)} (${pos})`);
console.log(` Before: ${before.toString('hex')}`); console.log(` Before: ${before.toString('hex')}`);
console.log(` Old pattern: ${oldBytes.slice(0, 20).toString('hex')}${oldBytes.length > 20 ? '...' : ''}`); console.log(` Old pattern: ${oldBytes.slice(0, 20).toString('hex')}${oldBytes.length > 20 ? '...' : ''}`);
console.log(` After: ${after.toString('hex')}`); console.log(` After: ${after.toString('hex')}`);
@@ -216,6 +236,7 @@ class ClientPatcher {
result.fill(0x00, pos, pos + oldBytes.length); result.fill(0x00, pos, pos + oldBytes.length);
} }
newBytes.copy(result, pos); newBytes.copy(result, pos);
patchedCount++;
count++; count++;
} }