Fix tickrate and action queue stuff

This commit is contained in:
2025-01-13 10:00:23 +01:00
parent 8d70129c73
commit 0a58e0453a
6 changed files with 47 additions and 77 deletions
+41 -41
View File
@@ -41,26 +41,19 @@ func ConnectToServer() (net.Conn, int32, error) {
}
func HandleServerCommunication(conn net.Conn, playerID int32, player *Player, otherPlayers map[int32]*Player) {
// Ticker for sending actions aligned with server ticks
ticker := time.NewTicker(ServerTickRate)
defer ticker.Stop()
buf := make([]byte, 4096)
// Ticker for sending actions
actionTicker := time.NewTicker(ClientTickRate)
defer actionTicker.Stop()
// Goroutine to handle sending player's actions to the server
go func() {
for range ticker.C {
for range actionTicker.C {
player.Lock()
if len(player.ActionQueue) > 0 {
// Bundle all actions that occurred during this tick
actions := make([]*pb.Action, 0, len(player.ActionQueue))
for _, actionData := range player.ActionQueue {
action := &pb.Action{
PlayerId: playerID,
Type: pb.Action_MOVE,
X: int32(actionData.X),
Y: int32(actionData.Y),
}
actions = append(actions, action)
}
actions := make([]*pb.Action, len(player.ActionQueue))
copy(actions, player.ActionQueue) // Copy to avoid holding lock while sending
// Create a batch message
batch := &pb.ActionBatch{
@@ -69,29 +62,29 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *Player, ot
Tick: player.CurrentTick,
}
// Serialize the batch
// Clear the action queue after copying
player.ActionQueue = player.ActionQueue[:0]
player.Unlock()
// Serialize and send the batch
data, err := proto.Marshal(batch)
if err != nil {
log.Printf("Failed to marshal action batch: %v", err)
continue
}
// Send batch to server
_, err = conn.Write(data)
if err != nil {
if _, err = conn.Write(data); err != nil {
log.Printf("Failed to send actions to server: %v", err)
return
}
// Clear the action queue after sending
player.ActionQueue = player.ActionQueue[:0]
} else {
player.Unlock()
}
}
}()
// Main loop to handle receiving updates from the server
for {
buf := make([]byte, 4096)
n, err := conn.Read(buf)
if err != nil {
log.Printf("Failed to read from server: %v", err)
@@ -104,27 +97,34 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *Player, ot
continue
}
// Check for tick synchronization
tickDiff := serverMessage.CurrentTick - player.CurrentTick
if tickDiff > MaxTickDesync {
log.Printf("Client too far behind (tick diff: %d), forcing resync", tickDiff)
player.ForceResync(serverMessage.Players[playerID])
}
// Update player's current tick
// Update game state with received data
player.Lock()
player.CurrentTick = serverMessage.CurrentTick
// Update other players' states
for _, state := range serverMessage.Players {
if state.PlayerId != playerID {
if otherPlayer, exists := otherPlayers[state.PlayerId]; exists {
// Calculate interpolation based on server tick
otherPlayer.UpdatePosition(state, ServerTickRate)
} else {
// Initialize new player
otherPlayers[state.PlayerId] = NewPlayer(state)
// Check for desync
tickDiff := serverMessage.CurrentTick - player.CurrentTick
if tickDiff > MaxTickDesync {
// Force resync if we're too far behind
for _, state := range serverMessage.Players {
if state.PlayerId == playerID {
player.ForceResync(state)
break
}
}
}
player.Unlock()
// Update other players
for _, state := range serverMessage.Players {
if state.PlayerId == playerID {
continue // Skip self
}
if otherPlayer, exists := otherPlayers[state.PlayerId]; exists {
otherPlayer.UpdatePosition(state, ServerTickRate)
} else {
otherPlayers[state.PlayerId] = NewPlayer(state)
}
}
}
}