191 lines
6.0 KiB
JavaScript
191 lines
6.0 KiB
JavaScript
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;
|
|
|
|
if (typeof DEBUG_SYNC !== 'undefined' && DEBUG_SYNC) {
|
|
compareState(snapshotobstacles, data.serverObs);
|
|
}
|
|
|
|
if (data.powerups) {
|
|
const sTick = data.serverTick;
|
|
|
|
if (lastPowerupTick > sTick) {
|
|
} else {
|
|
godModeLives = data.powerups.godLives;
|
|
hasBat = data.powerups.hasBat;
|
|
bootTicks = data.powerups.bootTicks;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
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 = "<h3>BESTENLISTE</h3>";
|
|
entries.forEach(e => {
|
|
const color = e.isMe ? "yellow" : "white";
|
|
html += `<div style="display:flex; justify-content:space-between; color:${color}; margin-bottom:5px;">
|
|
<span>#${e.rank} ${e.name}</span><span>${Math.floor(e.score/10)}</span></div>`;
|
|
});
|
|
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 = "<div style='padding:20px'>Noch keine Scores.</div>"; 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 += `<div class="hof-entry"><span><span class="hof-rank">${icon}</span> ${e.name}</span><span class="hof-score">${Math.floor(e.score / 10)}</span></div>`;
|
|
});
|
|
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
|
|
}
|
|
} |