fix README, SYNC, DATENSCHUTZ
Some checks failed
Dynamic Branch Deploy / build-and-deploy (push) Has been cancelled
Some checks failed
Dynamic Branch Deploy / build-and-deploy (push) Has been cancelled
This commit is contained in:
@@ -1,35 +1,18 @@
|
||||
// ==========================================
|
||||
// NETZWERK LOGIK (WEBSOCKET + RTT SYNC)
|
||||
// ==========================================
|
||||
|
||||
/*
|
||||
GLOBALE VARIABLEN (aus state.js):
|
||||
- socket
|
||||
- obstacleBuffer, platformBuffer
|
||||
- currentLatencyMs, pingInterval
|
||||
- isGameRunning, isGameOver
|
||||
- score, currentTick
|
||||
*/
|
||||
|
||||
function connectGame() {
|
||||
// Alte Verbindung schließen
|
||||
if (socket) {
|
||||
socket.close();
|
||||
}
|
||||
|
||||
// Ping Timer stoppen falls aktiv
|
||||
if (typeof pingInterval !== 'undefined' && pingInterval) {
|
||||
clearInterval(pingInterval);
|
||||
}
|
||||
|
||||
// Protokoll automatisch wählen (ws:// oder wss://)
|
||||
const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const url = proto + "//" + location.host + "/ws";
|
||||
|
||||
console.log("Verbinde zu:", url);
|
||||
socket = new WebSocket(url);
|
||||
|
||||
// --- 1. VERBINDUNG GEÖFFNET ---
|
||||
socket.onopen = () => {
|
||||
console.log("🟢 WS Verbunden. Spiel startet.");
|
||||
|
||||
@@ -38,88 +21,72 @@ function connectGame() {
|
||||
platformBuffer = [];
|
||||
obstacles = [];
|
||||
platforms = [];
|
||||
currentLatencyMs = 0; // Reset Latenz
|
||||
currentLatencyMs = 0;
|
||||
|
||||
isGameRunning = true;
|
||||
isGameOver = false;
|
||||
isLoaded = true;
|
||||
|
||||
// PING LOOP STARTEN (Jede Sekunde messen)
|
||||
pingInterval = setInterval(sendPing, 1000);
|
||||
|
||||
// Game Loop anwerfen
|
||||
requestAnimationFrame(gameLoop);
|
||||
};
|
||||
|
||||
// --- 2. NACHRICHT VOM SERVER ---
|
||||
socket.onmessage = (event) => {
|
||||
try {
|
||||
const msg = JSON.parse(event.data);
|
||||
|
||||
// A. PONG (Latenzmessung)
|
||||
if (msg.type === "pong") {
|
||||
const now = Date.now();
|
||||
const sentTime = msg.ts; // Server schickt unseren Timestamp zurück
|
||||
const sentTime = msg.ts;
|
||||
|
||||
|
||||
// Round Trip Time (Hin + Zurück)
|
||||
const rtt = now - sentTime;
|
||||
|
||||
// One Way Latency (Latenz in eine Richtung)
|
||||
|
||||
const latency = rtt / 2;
|
||||
|
||||
// Glätten (Exponential Moving Average), damit Werte nicht springen
|
||||
// Wenn es der erste Wert ist, nehmen wir ihn direkt.
|
||||
|
||||
if (currentLatencyMs === 0) {
|
||||
currentLatencyMs = latency;
|
||||
} else {
|
||||
// 90% alter Wert, 10% neuer Wert
|
||||
|
||||
currentLatencyMs = (currentLatencyMs * 0.9) + (latency * 0.1);
|
||||
}
|
||||
|
||||
// Optional: Debugging im Log
|
||||
// console.log(`📡 Ping: ${rtt}ms | Latenz: ${currentLatencyMs.toFixed(1)}ms`);
|
||||
}
|
||||
|
||||
// B. CHUNK (Objekte empfangen)
|
||||
|
||||
if (msg.type === "chunk") {
|
||||
|
||||
// 1. CLOCK SYNC (Die Zeitmaschine)
|
||||
// Wenn der Server bei Tick 204 ist und wir bei 182, müssen wir aufholen!
|
||||
// Wir addieren die geschätzte Latenz (in Ticks) auf die Serverzeit.
|
||||
// 60 FPS = 16ms/Tick. 20 TPS = 50ms/Tick.
|
||||
|
||||
const msPerTick = 1000 / 20; // WICHTIG: Wir laufen auf 20 TPS Basis!
|
||||
const msPerTick = 1000 / 20;
|
||||
const latencyInTicks = Math.floor(currentLatencyMs / msPerTick);
|
||||
|
||||
// Ziel-Zeit: Server-Zeit + Übertragungsweg
|
||||
|
||||
const targetTick = msg.serverTick + latencyInTicks;
|
||||
const drift = targetTick - currentTick;
|
||||
|
||||
// Wenn wir mehr als 2 Ticks abweichen -> Korrigieren
|
||||
|
||||
if (Math.abs(drift) > 2) {
|
||||
// console.log(`⏰ Clock Sync: ${currentTick} -> ${targetTick} (Drift: ${drift})`);
|
||||
currentTick = targetTick; // Harter Sync, damit Physik stimmt
|
||||
currentTick = targetTick;
|
||||
}
|
||||
|
||||
// 2. PIXEL KORREKTUR (Sanfter!)
|
||||
// Wir berechnen den Speed
|
||||
|
||||
let sTick = msg.serverTick;
|
||||
// Formel aus logic.js (Base 15 + Zeit)
|
||||
let currentSpeedPerTick = 15.0 + (sTick / 1000.0) * 1.5;
|
||||
if (currentSpeedPerTick > 36) currentSpeedPerTick = 36;
|
||||
|
||||
const speedPerMs = currentSpeedPerTick / msPerTick; // Speed pro MS
|
||||
const speedPerMs = currentSpeedPerTick / msPerTick;
|
||||
|
||||
|
||||
// Korrektur: Latenz * Speed
|
||||
// FIX: Wir kappen die Korrektur bei max 100px, damit Objekte nicht "teleportieren".
|
||||
let dynamicCorrection = (currentLatencyMs * speedPerMs) + 5;
|
||||
if (dynamicCorrection > 100) dynamicCorrection = 100; // Limit
|
||||
|
||||
// Puffer füllen (mit Limit)
|
||||
|
||||
if (msg.obstacles) {
|
||||
msg.obstacles.forEach(o => {
|
||||
o.x -= dynamicCorrection;
|
||||
// Init für Interpolation
|
||||
o.prevX = o.x;
|
||||
obstacleBuffer.push(o);
|
||||
});
|
||||
@@ -135,7 +102,6 @@ function connectGame() {
|
||||
|
||||
if (msg.score !== undefined) score = msg.score;
|
||||
|
||||
// Powerups übernehmen (für Anzeige)
|
||||
if (msg.powerups) {
|
||||
godModeLives = msg.powerups.godLives;
|
||||
hasBat = msg.powerups.hasBat;
|
||||
@@ -154,7 +120,6 @@ function connectGame() {
|
||||
}
|
||||
}
|
||||
|
||||
// C. TOD (Server Authoritative)
|
||||
if (msg.type === "dead") {
|
||||
console.log("💀 Server sagt: Game Over");
|
||||
|
||||
@@ -171,15 +136,11 @@ function connectGame() {
|
||||
|
||||
|
||||
|
||||
// 1. CLIENT SPEED BERECHNEN (Formel aus logic.js)
|
||||
// Wir nutzen hier 'score', da logic.js das auch tut
|
||||
let clientSpeed = BASE_SPEED + (currentTick / 1000.0) * 1.5;
|
||||
if (clientSpeed > 36.0) clientSpeed = 36.0;
|
||||
|
||||
// 2. SERVER SPEED HOLEN
|
||||
let serverSpeed = msg.currentSpeed || 0;
|
||||
|
||||
// 3. DIFF BERECHNEN
|
||||
let diffSpeed = clientSpeed - serverSpeed;
|
||||
let speedIcon = Math.abs(diffSpeed) < 0.01 ? "✅" : "❌";
|
||||
|
||||
@@ -194,12 +155,10 @@ function connectGame() {
|
||||
console.warn(`⚠️ ACHTUNG: Geschwindigkeiten weichen ab! Diff: ${diffSpeed.toFixed(4)}`);
|
||||
console.warn("Ursache: Client nutzt 'Score', Server nutzt 'Ticks'. Sind diese synchron?");
|
||||
}
|
||||
// -----------------------------
|
||||
|
||||
// 1. Hindernisse vergleichen
|
||||
generateSyncTable("Obstacles", obstacles, msg.obstacles);
|
||||
|
||||
// 2. Plattformen vergleichen
|
||||
|
||||
generateSyncTable("Platforms", platforms, msg.platforms);
|
||||
|
||||
console.groupEnd();
|
||||
@@ -210,7 +169,7 @@ function connectGame() {
|
||||
}
|
||||
};
|
||||
|
||||
// --- 3. VERBINDUNG GETRENNT ---
|
||||
|
||||
socket.onclose = () => {
|
||||
console.log("🔴 WS Verbindung getrennt.");
|
||||
if (pingInterval) clearInterval(pingInterval);
|
||||
@@ -221,13 +180,9 @@ function connectGame() {
|
||||
};
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// PING SENDEN
|
||||
// ==========================================
|
||||
|
||||
function sendPing() {
|
||||
if (socket && socket.readyState === WebSocket.OPEN) {
|
||||
// Wir senden den aktuellen Zeitstempel
|
||||
// Der Server muss diesen im "tick" Feld zurückschicken (siehe websocket.go)
|
||||
socket.send(JSON.stringify({
|
||||
type: "ping",
|
||||
tick: Date.now() // Timestamp als Integer
|
||||
@@ -235,9 +190,6 @@ function sendPing() {
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// INPUT SENDEN
|
||||
// ==========================================
|
||||
function sendInput(type, action) {
|
||||
if (socket && socket.readyState === WebSocket.OPEN) {
|
||||
socket.send(JSON.stringify({
|
||||
@@ -256,37 +208,33 @@ function generateSyncTable(label, clientList, serverList) {
|
||||
const report = [];
|
||||
const matchedServerIndices = new Set();
|
||||
|
||||
// 1. Parameter für Latenz-Korrektur berechnen
|
||||
// Damit wir wissen: "Wo MÜSSTE das Server-Objekt auf dem Client sein?"
|
||||
const msPerTick = 50; // Bei 20 TPS
|
||||
|
||||
// Speed Schätzung (gleiche Formel wie in logic.js)
|
||||
const msPerTick = 50;
|
||||
|
||||
|
||||
let debugSpeed = 15.0 + (score / 1000.0) * 1.5;
|
||||
if (debugSpeed > 36) debugSpeed = 36;
|
||||
|
||||
const speedPerMs = debugSpeed / msPerTick;
|
||||
|
||||
// Pixel, die das Objekt wegen Ping weiter "links" sein müsste
|
||||
|
||||
const latencyPx = currentLatencyMs * speedPerMs;
|
||||
|
||||
// 2. Client Objekte durchgehen
|
||||
|
||||
clientList.forEach((cObj) => {
|
||||
let bestMatch = null;
|
||||
let bestDist = 9999;
|
||||
let bestSIdx = -1;
|
||||
|
||||
// ID sicherstellen
|
||||
|
||||
const cID = cObj.def ? cObj.def.id : (cObj.id || "unknown");
|
||||
|
||||
// Passendes Server-Objekt suchen
|
||||
|
||||
serverList.forEach((sObj, sIdx) => {
|
||||
if (matchedServerIndices.has(sIdx)) return;
|
||||
|
||||
const sID = sObj.id || "unknown";
|
||||
|
||||
// Match Kriterien:
|
||||
// 1. Gleiche ID (oder Plattform)
|
||||
// 2. Nähe (Wir vergleichen hier die korrigierte Position!)
|
||||
const sPosCorrected = sObj.x - latencyPx;
|
||||
const dist = Math.abs(cObj.x - sPosCorrected);
|
||||
|
||||
@@ -310,12 +258,10 @@ function generateSyncTable(label, clientList, serverList) {
|
||||
matchedServerIndices.add(bestSIdx);
|
||||
|
||||
serverXRaw = bestMatch.x;
|
||||
serverXCorrected = bestMatch.x - latencyPx; // Hier rechnen wir den Ping raus
|
||||
serverXCorrected = bestMatch.x - latencyPx;
|
||||
|
||||
// Der "Wahrs" Drift: Differenz nach Latenz-Abzug
|
||||
diffReal = cObj.x - serverXCorrected;
|
||||
|
||||
// Status Bestimmung
|
||||
const absDiff = Math.abs(diffReal);
|
||||
if (absDiff < 20) status = "✅ PERFECT";
|
||||
else if (absDiff < 60) status = "🆗 OK";
|
||||
@@ -333,10 +279,8 @@ function generateSyncTable(label, clientList, serverList) {
|
||||
});
|
||||
});
|
||||
|
||||
// 3. Fehlende Server Objekte finden
|
||||
serverList.forEach((sObj, sIdx) => {
|
||||
if (!matchedServerIndices.has(sIdx)) {
|
||||
// Prüfen, ob es vielleicht einfach noch unsichtbar ist (Zukunft)
|
||||
const sPosCorrected = sObj.x - latencyPx;
|
||||
let status = "❌ MISSING";
|
||||
|
||||
@@ -354,7 +298,6 @@ function generateSyncTable(label, clientList, serverList) {
|
||||
}
|
||||
});
|
||||
|
||||
// 4. Sortieren nach Position (links nach rechts)
|
||||
report.sort((a, b) => {
|
||||
const valA = (typeof a["Client X"] === 'number') ? a["Client X"] : a["Server X (Sim)"];
|
||||
const valB = (typeof b["Client X"] === 'number') ? b["Client X"] : b["Server X (Sim)"];
|
||||
|
||||
Reference in New Issue
Block a user