package main import ( "git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/config" "git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/game" ) // ApplyInput wendet einen Input auf den vorhergesagten Zustand an func (g *Game) ApplyInput(input InputState) { // Horizontale Bewegung moveX := 0.0 if input.Left { moveX = -1.0 } else if input.Right { moveX = 1.0 } speed := config.RunSpeed + (moveX * 4.0) g.predictedX += speed // Gravitation g.predictedVY += config.Gravity if g.predictedVY > config.MaxFall { g.predictedVY = config.MaxFall } // Fast Fall if input.Down { g.predictedVY = 15.0 } // Sprung if input.Jump && g.predictedGround { g.predictedVY = -14.0 g.predictedGround = false } // Vertikale Bewegung g.predictedY += g.predictedVY // Einfache Boden-Kollision (hardcoded für jetzt) if g.predictedY >= 540 { g.predictedY = 540 g.predictedVY = 0 g.predictedGround = true } else { g.predictedGround = false } } // ReconcileWithServer gleicht lokale Prediction mit Server-State ab func (g *Game) ReconcileWithServer(serverState game.PlayerState) { g.predictionMutex.Lock() defer g.predictionMutex.Unlock() // Server-bestätigte Sequenz g.lastServerSeq = serverState.LastInputSeq // Entferne alle bestätigten Inputs for seq := range g.pendingInputs { if seq <= g.lastServerSeq { delete(g.pendingInputs, seq) } } // Temporäre Position für Replay replayX := serverState.X replayY := serverState.Y replayVX := serverState.VX replayVY := serverState.VY replayGround := serverState.OnGround // Replay alle noch nicht bestätigten Inputs if len(g.pendingInputs) > 0 { for seq := g.lastServerSeq + 1; seq <= g.inputSequence; seq++ { if input, ok := g.pendingInputs[seq]; ok { // Temporär auf Replay-Position setzen oldX, oldY := g.predictedX, g.predictedY oldVX, oldVY := g.predictedVX, g.predictedVY oldGround := g.predictedGround g.predictedX = replayX g.predictedY = replayY g.predictedVX = replayVX g.predictedVY = replayVY g.predictedGround = replayGround g.ApplyInput(input) replayX = g.predictedX replayY = g.predictedY replayVX = g.predictedVX replayVY = g.predictedVY replayGround = g.predictedGround // Zurücksetzen g.predictedX = oldX g.predictedY = oldY g.predictedVX = oldVX g.predictedVY = oldVY g.predictedGround = oldGround } } } // Berechne Differenz zwischen aktueller Prediction und Server-Replay diffX := replayX - g.predictedX diffY := replayY - g.predictedY // Nur korrigieren wenn Differenz signifikant (> 5 Pixel) const threshold = 5.0 if diffX*diffX+diffY*diffY > threshold*threshold { // Speichere Korrektur für sanfte Interpolation g.correctionX = diffX g.correctionY = diffY } // Velocity und Ground immer sofort übernehmen g.predictedVX = replayVX g.predictedVY = replayVY g.predictedGround = replayGround }