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
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 9m53s
This commit is contained in:
@@ -85,6 +85,13 @@ func (g *Game) wsReadPump() {
|
|||||||
payloadBytes, _ := json.Marshal(msg.Payload)
|
payloadBytes, _ := json.Marshal(msg.Payload)
|
||||||
var state game.GameState
|
var state game.GameState
|
||||||
if err := json.Unmarshal(payloadBytes, &state); err == nil {
|
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)
|
// Server Reconciliation für lokalen Spieler (VOR dem Lock)
|
||||||
for _, p := range state.Players {
|
for _, p := range state.Players {
|
||||||
if p.Name == g.playerName {
|
if p.Name == g.playerName {
|
||||||
|
|||||||
@@ -72,6 +72,13 @@ func (g *Game) connectToServer() {
|
|||||||
payloadBytes, _ := json.Marshal(msg.Payload)
|
payloadBytes, _ := json.Marshal(msg.Payload)
|
||||||
var state game.GameState
|
var state game.GameState
|
||||||
if err := json.Unmarshal(payloadBytes, &state); err == nil {
|
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)
|
// Server Reconciliation für lokalen Spieler (VOR dem Lock)
|
||||||
for _, p := range state.Players {
|
for _, p := range state.Players {
|
||||||
if p.Name == g.playerName {
|
if p.Name == g.playerName {
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ type Game struct {
|
|||||||
pendingInputs map[uint32]InputState // Noch nicht bestätigte Inputs
|
pendingInputs map[uint32]InputState // Noch nicht bestätigte Inputs
|
||||||
lastServerSeq uint32 // Letzte vom Server bestätigte Sequenz
|
lastServerSeq uint32 // Letzte vom Server bestätigte Sequenz
|
||||||
predictionMutex sync.Mutex // Mutex für pendingInputs
|
predictionMutex sync.Mutex // Mutex für pendingInputs
|
||||||
|
lastRecvSeq uint32 // Letzte empfangene Server-Sequenznummer (für Out-of-Order-Erkennung)
|
||||||
|
|
||||||
// Smooth Correction
|
// Smooth Correction
|
||||||
correctionX float64 // Verbleibende Korrektur in X
|
correctionX float64 // Verbleibende Korrektur in X
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ type GameState struct {
|
|||||||
CollectedCoins map[string]bool `json:"collected_coins"` // Welche Coins wurden eingesammelt (Key: ChunkID_ObjectIndex)
|
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
|
CollectedPowerups map[string]bool `json:"collected_powerups"` // Welche Powerups wurden eingesammelt
|
||||||
MovingPlatforms []MovingPlatformSync `json:"moving_platforms"` // Bewegende Plattformen
|
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
|
// MovingPlatformSync: Synchronisiert die Position einer bewegenden Plattform
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ type Room struct {
|
|||||||
ChunkSpawnedCount map[string]int // Wie oft wurde jeder Chunk gespawnt
|
ChunkSpawnedCount map[string]int // Wie oft wurde jeder Chunk gespawnt
|
||||||
MovingPlatforms []*MovingPlatform // Aktive bewegende Plattformen
|
MovingPlatforms []*MovingPlatform // Aktive bewegende Plattformen
|
||||||
firstBroadcast bool // Wurde bereits geloggt?
|
firstBroadcast bool // Wurde bereits geloggt?
|
||||||
|
sequence uint32 // Sequenznummer für Broadcasts
|
||||||
|
|
||||||
stopChan chan struct{}
|
stopChan chan struct{}
|
||||||
|
|
||||||
@@ -784,6 +785,9 @@ func (r *Room) Broadcast() {
|
|||||||
r.Mutex.RLock()
|
r.Mutex.RLock()
|
||||||
defer r.Mutex.RUnlock()
|
defer r.Mutex.RUnlock()
|
||||||
|
|
||||||
|
// Sequenznummer erhöhen
|
||||||
|
r.sequence++
|
||||||
|
|
||||||
state := game.GameState{
|
state := game.GameState{
|
||||||
RoomID: r.ID,
|
RoomID: r.ID,
|
||||||
Players: make(map[string]game.PlayerState),
|
Players: make(map[string]game.PlayerState),
|
||||||
@@ -797,6 +801,7 @@ func (r *Room) Broadcast() {
|
|||||||
CollectedCoins: r.CollectedCoins,
|
CollectedCoins: r.CollectedCoins,
|
||||||
CollectedPowerups: r.CollectedPowerups,
|
CollectedPowerups: r.CollectedPowerups,
|
||||||
MovingPlatforms: make([]game.MovingPlatformSync, 0, len(r.MovingPlatforms)),
|
MovingPlatforms: make([]game.MovingPlatformSync, 0, len(r.MovingPlatforms)),
|
||||||
|
Sequence: r.sequence,
|
||||||
}
|
}
|
||||||
|
|
||||||
for id, p := range r.Players {
|
for id, p := range r.Players {
|
||||||
|
|||||||
Reference in New Issue
Block a user