Prevent chat and other player rendering race conditions when logging in at the same time

This commit is contained in:
2025-04-16 12:28:30 +02:00
parent 62a6bb2926
commit 541f53c06a
3 changed files with 133 additions and 37 deletions

View File

@ -91,6 +91,22 @@ func (mh *MessageHandler) WriteMessage(msg proto.Message) error {
// UpdateGameState processes a server message and updates game state
func UpdateGameState(serverMessage *pb.ServerMessage, player *types.Player, otherPlayers map[int32]*types.Player) {
// Safety check for nil inputs
if serverMessage == nil {
log.Printf("Warning: Received nil server message")
return
}
if player == nil {
log.Printf("Warning: Local player is nil when updating game state")
return
}
if otherPlayers == nil {
log.Printf("Warning: otherPlayers map is nil when updating game state")
return
}
playerID := player.ID
player.Lock()
@ -99,7 +115,7 @@ func UpdateGameState(serverMessage *pb.ServerMessage, player *types.Player, othe
tickDiff := serverMessage.CurrentTick - player.CurrentTick
if tickDiff > types.MaxTickDesync {
for _, state := range serverMessage.Players {
if state.PlayerId == playerID {
if state != nil && state.PlayerId == playerID {
player.ForceResync(state)
break
}
@ -110,6 +126,12 @@ func UpdateGameState(serverMessage *pb.ServerMessage, player *types.Player, othe
// Process player states
validPlayerIds := make(map[int32]bool)
for _, state := range serverMessage.Players {
// Skip invalid player states
if state == nil {
log.Printf("Warning: Received nil player state")
continue
}
validPlayerIds[state.PlayerId] = true
if state.PlayerId == playerID {
@ -129,7 +151,13 @@ func UpdateGameState(serverMessage *pb.ServerMessage, player *types.Player, othe
// Update or create other players
if otherPlayer, exists := otherPlayers[state.PlayerId]; exists {
otherPlayer.UpdatePosition(state, types.ServerTickRate)
if otherPlayer != nil {
otherPlayer.UpdatePosition(state, types.ServerTickRate)
} else {
// Replace nil player with a new one
log.Printf("Replacing nil player with ID: %d", state.PlayerId)
otherPlayers[state.PlayerId] = types.NewPlayer(state)
}
} else {
log.Printf("Creating new player with ID: %d", state.PlayerId)
otherPlayers[state.PlayerId] = types.NewPlayer(state)
@ -144,14 +172,32 @@ func UpdateGameState(serverMessage *pb.ServerMessage, player *types.Player, othe
}
}
// Handle chat messages
if handler, ok := player.UserData.(types.ChatMessageHandler); ok && len(serverMessage.ChatMessages) > 0 {
// Handle chat messages with safety checks
if handler, ok := player.UserData.(types.ChatMessageHandler); ok && handler != nil && len(serverMessage.ChatMessages) > 0 {
log.Printf("Received %d chat messages from server", len(serverMessage.ChatMessages))
handler.HandleServerMessages(serverMessage.ChatMessages)
// Update the last seen message timestamp to the most recent message
if len(serverMessage.ChatMessages) > 0 {
lastMsg := serverMessage.ChatMessages[len(serverMessage.ChatMessages)-1]
// Make sure we have valid chat messages
validMessages := make([]*pb.ChatMessage, 0, len(serverMessage.ChatMessages))
for _, msg := range serverMessage.ChatMessages {
if msg != nil {
validMessages = append(validMessages, msg)
}
}
if len(validMessages) > 0 {
// Use a separate goroutine to handle messages to prevent blocking
// network handling if there's an issue with chat processing
go func(msgs []*pb.ChatMessage) {
defer func() {
if r := recover(); r != nil {
log.Printf("Recovered from panic in chat message handler: %v", r)
}
}()
handler.HandleServerMessages(msgs)
}(validMessages)
// Update the last seen message timestamp to the most recent message
lastMsg := validMessages[len(validMessages)-1]
lastSeenMessageTimestamp = lastMsg.Timestamp
log.Printf("Updated last seen message timestamp to %d", lastSeenMessageTimestamp)
}