async function sendChunk() {
const ticksToSend = currentTick - lastSentTick;
if (ticksToSend <= 0) return;
const snapshotobstacles = JSON.parse(JSON.stringify(obstacles));
const payload = {
sessionId: sessionID,
inputs: [...inputLog],
totalTicks: ticksToSend
};
inputLog = [];
lastSentTick = currentTick;
try {
const res = await fetch('/api/validate', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(payload)
});
const data = await res.json();
// Update für visuelles Debugging
if (data.serverObs) {
serverObstacles = data.serverObs;
// --- NEU: DEBUG MODUS VERGLEICH ---
if (typeof DEBUG_SYNC !== 'undefined' && DEBUG_SYNC) {
compareState(snapshotobstacles, data.serverObs);
}
// ----------------------------------
}
if (data.status === "dead") {
console.error("💀 SERVER KILL", data);
gameOver("Vom Server gestoppt");
} else {
const sScore = data.verifiedScore;
// Score Korrektur
if (Math.abs(score - sScore) > 200) {
console.warn(`⚠️ SCORE DRIFT: Client=${score} Server=${sScore}`);
score = sScore;
}
}
} catch (e) {
console.error("Netzwerkfehler:", e);
}
}
window.submitScore = async function() {
const nameInput = document.getElementById('playerNameInput');
const name = nameInput.value;
const btn = document.getElementById('submitBtn');
if (!name) return alert("Namen eingeben!");
btn.disabled = true;
try {
const res = await fetch('/api/submit-name', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ sessionId: sessionID, name: name })
});
const data = await res.json();
let myClaims = JSON.parse(localStorage.getItem('escape_claims') || '[]');
myClaims.push({
name: name, score: Math.floor(score / 10), code: data.claimCode,
date: new Date().toLocaleString('de-DE'), sessionId: sessionID
});
localStorage.setItem('escape_claims', JSON.stringify(myClaims));
document.getElementById('inputSection').style.display = 'none';
loadLeaderboard();
} catch (e) {}
};
async function loadLeaderboard() {
const res = await fetch(`/api/leaderboard?sessionId=${sessionID}`);
const entries = await res.json();
let html = "
BESTENLISTE
";
entries.forEach(e => {
const color = e.isMe ? "yellow" : "white";
html += `
#${e.rank} ${e.name}${Math.floor(e.score/10)}
`;
});
document.getElementById('leaderboard').innerHTML = html;
}
async function loadStartScreenLeaderboard() {
try {
const listEl = document.getElementById('startLeaderboardList');
if (!listEl) return;
const res = await fetch('/api/leaderboard');
const entries = await res.json();
if (entries.length === 0) { listEl.innerHTML = "Noch keine Scores.
"; return; }
let html = "";
entries.forEach(e => {
let icon = "#" + e.rank;
if (e.rank === 1) icon = "🥇"; if (e.rank === 2) icon = "🥈"; if (e.rank === 3) icon = "🥉";
html += `${icon} ${e.name}${Math.floor(e.score / 10)}
`;
});
listEl.innerHTML = html;
} catch (e) {}
}
function compareState(clientObs, serverObs) {
// 1. Anzahl prüfen
if (clientObs.length !== serverObs.length) {
console.error(`🚨 ANZAHL MISMATCH! Client: ${clientObs.length}, Server: ${serverObs.length}`);
}
const report = [];
const maxLen = Math.max(clientObs.length, serverObs.length);
let hasMajorDrift = false;
for (let i = 0; i < maxLen; i++) {
const cli = clientObs[i];
const srv = serverObs[i];
let drift = 0;
let status = "✅ OK";
// Client Objekt vorbereiten
let cID = "---";
let cX = 0;
if (cli) {
cID = cli.def.id; // Struktur beachten: cli.def.id
cX = cli.x;
}
// Server Objekt vorbereiten
let sID = "---";
let sX = 0;
if (srv) {
sID = srv.id; // Struktur vom Server: srv.id
sX = srv.x;
}
// Vergleich
if (cli && srv) {
// IDs unterschiedlich? (z.B. Tisch vs Lehrer)
if (cID !== sID) {
status = "❌ ID ERROR";
hasMajorDrift = true;
} else {
drift = cX - sX;
if (Math.abs(drift) > SYNC_TOLERANCE) {
status = "⚠️ DRIFT";
hasMajorDrift = true;
}
}
} else {
status = "❌ MISSING";
hasMajorDrift = true;
}
// In Tabelle eintragen
report.push({
Index: i,
Status: status,
"C-ID": cID,
"S-ID": sID,
"C-Pos": cX.toFixed(1),
"S-Pos": sX.toFixed(1),
"Drift (px)": drift.toFixed(2)
});
}
// Nur loggen, wenn Fehler da sind oder alle 5 Sekunden (Tick 300)
if (hasMajorDrift || currentTick % 300 === 0) {
if (hasMajorDrift) console.warn("--- SYNC PROBLEME GEFUNDEN ---");
else console.log("--- Sync Check (Routine) ---");
console.table(report); // Das erstellt eine super lesbare Tabelle im Browser
}
}