Private
Public Access
1
0

Add sequence numbers to server broadcasts and client state handling for out-of-order update detection.
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 9m53s

This commit is contained in:
Sebastian Unterschütz
2026-01-06 18:52:27 +01:00
parent 2a635d0aaa
commit 23d42d42e7
5 changed files with 21 additions and 0 deletions

View File

@@ -85,6 +85,13 @@ func (g *Game) wsReadPump() {
payloadBytes, _ := json.Marshal(msg.Payload)
var state game.GameState
if err := json.Unmarshal(payloadBytes, &state); err == nil {
// Out-of-Order-Erkennung: Ignoriere alte Updates
if state.Sequence > 0 && state.Sequence <= g.lastRecvSeq {
// Alte Nachricht - ignorieren
continue
}
g.lastRecvSeq = state.Sequence
// Server Reconciliation für lokalen Spieler (VOR dem Lock)
for _, p := range state.Players {
if p.Name == g.playerName {

View File

@@ -72,6 +72,13 @@ func (g *Game) connectToServer() {
payloadBytes, _ := json.Marshal(msg.Payload)
var state game.GameState
if err := json.Unmarshal(payloadBytes, &state); err == nil {
// Out-of-Order-Erkennung: Ignoriere alte Updates
if state.Sequence > 0 && state.Sequence <= g.lastRecvSeq {
// Alte Nachricht - ignorieren
return nil
}
g.lastRecvSeq = state.Sequence
// Server Reconciliation für lokalen Spieler (VOR dem Lock)
for _, p := range state.Players {
if p.Name == g.playerName {

View File

@@ -92,6 +92,7 @@ type Game struct {
pendingInputs map[uint32]InputState // Noch nicht bestätigte Inputs
lastServerSeq uint32 // Letzte vom Server bestätigte Sequenz
predictionMutex sync.Mutex // Mutex für pendingInputs
lastRecvSeq uint32 // Letzte empfangene Server-Sequenznummer (für Out-of-Order-Erkennung)
// Smooth Correction
correctionX float64 // Verbleibende Korrektur in X

View File

@@ -113,6 +113,7 @@ type GameState struct {
CollectedCoins map[string]bool `json:"collected_coins"` // Welche Coins wurden eingesammelt (Key: ChunkID_ObjectIndex)
CollectedPowerups map[string]bool `json:"collected_powerups"` // Welche Powerups wurden eingesammelt
MovingPlatforms []MovingPlatformSync `json:"moving_platforms"` // Bewegende Plattformen
Sequence uint32 `json:"sequence"` // Sequenznummer für Out-of-Order-Erkennung
}
// MovingPlatformSync: Synchronisiert die Position einer bewegenden Plattform

View File

@@ -83,6 +83,7 @@ type Room struct {
ChunkSpawnedCount map[string]int // Wie oft wurde jeder Chunk gespawnt
MovingPlatforms []*MovingPlatform // Aktive bewegende Plattformen
firstBroadcast bool // Wurde bereits geloggt?
sequence uint32 // Sequenznummer für Broadcasts
stopChan chan struct{}
@@ -784,6 +785,9 @@ func (r *Room) Broadcast() {
r.Mutex.RLock()
defer r.Mutex.RUnlock()
// Sequenznummer erhöhen
r.sequence++
state := game.GameState{
RoomID: r.ID,
Players: make(map[string]game.PlayerState),
@@ -797,6 +801,7 @@ func (r *Room) Broadcast() {
CollectedCoins: r.CollectedCoins,
CollectedPowerups: r.CollectedPowerups,
MovingPlatforms: make([]game.MovingPlatformSync, 0, len(r.MovingPlatforms)),
Sequence: r.sequence,
}
for id, p := range r.Players {