Fix tickrate and action queue stuff

This commit is contained in:
bdnugget 2025-01-13 10:00:23 +01:00
parent 8d70129c73
commit 0a58e0453a
6 changed files with 47 additions and 77 deletions

View File

@ -1,32 +0,0 @@
syntax = "proto3";
package actions;
option go_package = "gitea.boner.be/bdnugget/goonserver/actions";
message Action {
enum ActionType {
MOVE = 0;
}
ActionType type = 1;
int32 x = 2;
int32 y = 3;
int32 player_id = 4;
}
message ActionBatch {
int32 player_id = 1;
repeated Action actions = 2;
int64 tick = 3;
}
message PlayerState {
int32 player_id = 1;
int32 x = 2;
int32 y = 3;
}
message ServerMessage {
int32 player_id = 1;
repeated PlayerState players = 2;
int64 current_tick = 3;
}

@ -1 +1 @@
Subproject commit 8290131998485ef62ccef43ddc7eb807c244ff67 Subproject commit a459e8b4a5cfa02f0ee588596dba5ce26afac39f

View File

@ -89,13 +89,13 @@ func main() {
rl.ClearBackground(rl.RayWhite) rl.ClearBackground(rl.RayWhite)
rl.BeginMode3D(camera) rl.BeginMode3D(camera)
DrawMap() DrawMap()
DrawPlayer(player, player.Model) DrawPlayer(&player, player.Model)
for id, other := range otherPlayers { for id, other := range otherPlayers {
if len(other.TargetPath) > 0 { if len(other.TargetPath) > 0 {
other.MoveTowards(other.TargetPath[0], deltaTime) other.MoveTowards(other.TargetPath[0], deltaTime)
} }
DrawPlayer(*other, models[int(id)%len(models)].Model) DrawPlayer(other, models[int(id)%len(models)].Model)
} }
rl.EndMode3D() rl.EndMode3D()

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) { func HandleServerCommunication(conn net.Conn, playerID int32, player *Player, otherPlayers map[int32]*Player) {
// Ticker for sending actions aligned with server ticks buf := make([]byte, 4096)
ticker := time.NewTicker(ServerTickRate)
defer ticker.Stop() // Ticker for sending actions
actionTicker := time.NewTicker(ClientTickRate)
defer actionTicker.Stop()
// Goroutine to handle sending player's actions to the server
go func() { go func() {
for range ticker.C { for range actionTicker.C {
player.Lock()
if len(player.ActionQueue) > 0 { if len(player.ActionQueue) > 0 {
// Bundle all actions that occurred during this tick // Bundle all actions that occurred during this tick
actions := make([]*pb.Action, 0, len(player.ActionQueue)) actions := make([]*pb.Action, len(player.ActionQueue))
copy(actions, player.ActionQueue) // Copy to avoid holding lock while sending
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)
}
// Create a batch message // Create a batch message
batch := &pb.ActionBatch{ batch := &pb.ActionBatch{
@ -69,29 +62,29 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *Player, ot
Tick: player.CurrentTick, 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) data, err := proto.Marshal(batch)
if err != nil { if err != nil {
log.Printf("Failed to marshal action batch: %v", err) log.Printf("Failed to marshal action batch: %v", err)
continue continue
} }
// Send batch to server if _, err = conn.Write(data); err != nil {
_, err = conn.Write(data)
if err != nil {
log.Printf("Failed to send actions to server: %v", err) log.Printf("Failed to send actions to server: %v", err)
return return
} }
} else {
// Clear the action queue after sending player.Unlock()
player.ActionQueue = player.ActionQueue[:0]
} }
} }
}() }()
// Main loop to handle receiving updates from the server // Main loop to handle receiving updates from the server
for { for {
buf := make([]byte, 4096)
n, err := conn.Read(buf) n, err := conn.Read(buf)
if err != nil { if err != nil {
log.Printf("Failed to read from server: %v", err) log.Printf("Failed to read from server: %v", err)
@ -104,27 +97,34 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *Player, ot
continue continue
} }
// Check for tick synchronization // Update game state with received data
tickDiff := serverMessage.CurrentTick - player.CurrentTick player.Lock()
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
player.CurrentTick = serverMessage.CurrentTick player.CurrentTick = serverMessage.CurrentTick
// Update other players' states // Check for desync
tickDiff := serverMessage.CurrentTick - player.CurrentTick
if tickDiff > MaxTickDesync {
// Force resync if we're too far behind
for _, state := range serverMessage.Players { for _, state := range serverMessage.Players {
if state.PlayerId != playerID { 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 { if otherPlayer, exists := otherPlayers[state.PlayerId]; exists {
// Calculate interpolation based on server tick
otherPlayer.UpdatePosition(state, ServerTickRate) otherPlayer.UpdatePosition(state, ServerTickRate)
} else { } else {
// Initialize new player
otherPlayers[state.PlayerId] = NewPlayer(state) otherPlayers[state.PlayerId] = NewPlayer(state)
} }
} }
} }
} }
}

View File

@ -7,7 +7,7 @@ import (
rl "github.com/gen2brain/raylib-go/raylib" rl "github.com/gen2brain/raylib-go/raylib"
) )
func DrawPlayer(player Player, model rl.Model) { func DrawPlayer(player *Player, model rl.Model) {
// Draw the player based on its actual position (PosActual) and current tile height // Draw the player based on its actual position (PosActual) and current tile height
playerPos := rl.Vector3{ playerPos := rl.Vector3{
X: player.PosActual.X, X: player.PosActual.X,

View File

@ -4,6 +4,7 @@ import (
pb "gitea.boner.be/bdnugget/goonserver/actions" pb "gitea.boner.be/bdnugget/goonserver/actions"
rl "github.com/gen2brain/raylib-go/raylib" rl "github.com/gen2brain/raylib-go/raylib"
"sync"
time "time" time "time"
) )
@ -14,6 +15,7 @@ type Tile struct {
} }
type Player struct { type Player struct {
sync.Mutex
PosActual rl.Vector3 PosActual rl.Vector3
PosTile Tile PosTile Tile
TargetPath []Tile TargetPath []Tile