fix conn handling; heartbeat and timeout
This commit is contained in:
parent
8d08958280
commit
34bbc39595
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
*.o
|
||||
|
||||
server/players.json
|
||||
client/game
|
||||
server/server
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
@ -124,6 +124,10 @@ class Game {
|
||||
std::string loginError = "";
|
||||
std::string currentUsername = "";
|
||||
|
||||
// Heartbeat timing
|
||||
float lastHeartbeatTime = 0.0f;
|
||||
const float HEARTBEAT_INTERVAL = 5.0f; // Send heartbeat every 5 seconds
|
||||
|
||||
public:
|
||||
Game() {
|
||||
InitWindow(1280, 720, "Multiplayer Terrain Game");
|
||||
@ -261,6 +265,14 @@ private:
|
||||
// Send normalized movement direction to server (server handles speed)
|
||||
if (moveInput.x != 0 || moveInput.z != 0) {
|
||||
network.sendMove(moveInput.x, 0, moveInput.z);
|
||||
lastHeartbeatTime = GetTime(); // Reset heartbeat timer when moving
|
||||
}
|
||||
|
||||
// Send periodic heartbeats when not moving
|
||||
float currentTime = GetTime();
|
||||
if (currentTime - lastHeartbeatTime >= HEARTBEAT_INTERVAL) {
|
||||
network.sendHeartbeat();
|
||||
lastHeartbeatTime = currentTime;
|
||||
}
|
||||
|
||||
// Handle color change with arrow keys
|
||||
|
||||
@ -250,6 +250,16 @@ void NetworkManager::sendColorChange(const std::string& newColor) {
|
||||
socket.send_to(buffer(msg), serverEndpoint);
|
||||
}
|
||||
|
||||
void NetworkManager::sendHeartbeat() {
|
||||
if (!connected) return;
|
||||
|
||||
std::array<uint8_t, 5> msg{};
|
||||
msg[0] = static_cast<uint8_t>(MessageType::Heartbeat);
|
||||
uint32_t id = playerID;
|
||||
std::memcpy(&msg[1], &id, sizeof(id));
|
||||
socket.send_to(buffer(msg), serverEndpoint);
|
||||
}
|
||||
|
||||
Vector3 NetworkManager::getPosition() {
|
||||
std::lock_guard lock(positionMutex);
|
||||
return serverPosition;
|
||||
|
||||
@ -24,7 +24,8 @@ enum class MessageType : uint8_t {
|
||||
ChangeColor = 0x09,
|
||||
ColorChanged = 0x0A,
|
||||
LoginResponse = 0x0B,
|
||||
Logout = 0x0C
|
||||
Logout = 0x0C,
|
||||
Heartbeat = 0x0D
|
||||
};
|
||||
|
||||
struct RemotePlayer {
|
||||
@ -44,6 +45,7 @@ public:
|
||||
void sendLogout();
|
||||
void sendMove(float dx, float dy, float dz);
|
||||
void sendColorChange(const std::string& newColor);
|
||||
void sendHeartbeat();
|
||||
|
||||
Vector3 getPosition();
|
||||
bool isConnected() const { return connected; }
|
||||
|
||||
@ -19,6 +19,7 @@ const (
|
||||
MSG_COLOR_CHANGED = 0x0A
|
||||
MSG_LOGIN_RESPONSE = 0x0B
|
||||
MSG_LOGOUT = 0x0C
|
||||
MSG_HEARTBEAT = 0x0D
|
||||
)
|
||||
|
||||
// Vec3 represents a 3D vector
|
||||
@ -184,3 +185,13 @@ func DecodeLogoutPacket(data []byte) (playerID uint32, ok bool) {
|
||||
playerID = binary.LittleEndian.Uint32(data[1:5])
|
||||
return playerID, true
|
||||
}
|
||||
|
||||
// DecodeHeartbeatPacket decodes a heartbeat packet
|
||||
func DecodeHeartbeatPacket(data []byte) (playerID uint32, ok bool) {
|
||||
if len(data) < 5 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
playerID = binary.LittleEndian.Uint32(data[1:5])
|
||||
return playerID, true
|
||||
}
|
||||
@ -83,7 +83,7 @@ func (s *Server) Run() error {
|
||||
|
||||
// Start player timeout checker
|
||||
go func() {
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
ticker := time.NewTicker(10 * time.Second)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
s.checkTimeouts()
|
||||
@ -115,6 +115,8 @@ func (s *Server) Run() error {
|
||||
s.handleColorChange(buffer[:n], addr)
|
||||
case MSG_LOGOUT:
|
||||
s.handleLogout(buffer[:n], addr)
|
||||
case MSG_HEARTBEAT:
|
||||
s.handleHeartbeat(buffer[:n], addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -210,7 +212,7 @@ func (s *Server) handleLogin(data []byte, addr *net.UDPAddr) {
|
||||
s.saveUserData()
|
||||
}
|
||||
|
||||
func (s *Server) handleMove(data []byte, _ *net.UDPAddr) {
|
||||
func (s *Server) handleMove(data []byte, addr *net.UDPAddr) {
|
||||
playerID, delta, ok := DecodeMovePacket(data)
|
||||
if !ok {
|
||||
return
|
||||
@ -223,6 +225,9 @@ func (s *Server) handleMove(data []byte, _ *net.UDPAddr) {
|
||||
return
|
||||
}
|
||||
|
||||
// Update the player's address in case it changed (NAT, port change, etc.)
|
||||
player.Address = addr
|
||||
|
||||
// Server-authoritative movement
|
||||
deltaTime := float32(0.016) // 60fps
|
||||
newX := player.Position.X + delta.X*15.0*deltaTime
|
||||
@ -289,7 +294,7 @@ func (s *Server) handleLogout(data []byte, _ *net.UDPAddr) {
|
||||
s.saveUserData()
|
||||
}
|
||||
|
||||
func (s *Server) handleColorChange(data []byte, _ *net.UDPAddr) {
|
||||
func (s *Server) handleColorChange(data []byte, addr *net.UDPAddr) {
|
||||
playerID, newColor, ok := DecodeColorChangePacket(data)
|
||||
if !ok {
|
||||
return
|
||||
@ -310,6 +315,9 @@ func (s *Server) handleColorChange(data []byte, _ *net.UDPAddr) {
|
||||
return
|
||||
}
|
||||
|
||||
// Update the player's address and last seen time
|
||||
player.Address = addr
|
||||
player.LastSeen = time.Now()
|
||||
player.Color = newColor
|
||||
|
||||
// Update persistent user data
|
||||
@ -404,6 +412,25 @@ func (s *Server) broadcastColorChanged(playerID uint32, color string) {
|
||||
s.mutex.RUnlock()
|
||||
}
|
||||
|
||||
func (s *Server) handleHeartbeat(data []byte, addr *net.UDPAddr) {
|
||||
playerID, ok := DecodeHeartbeatPacket(data)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
s.mutex.Lock()
|
||||
player, exists := s.players[playerID]
|
||||
if !exists {
|
||||
s.mutex.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
// Update the player's address and last seen time
|
||||
player.Address = addr
|
||||
player.LastSeen = time.Now()
|
||||
s.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (s *Server) checkTimeouts() {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
@ -1,20 +1,29 @@
|
||||
{
|
||||
"foo": {
|
||||
"username": "foo",
|
||||
"color": "orange",
|
||||
"position": {
|
||||
"X": -25.698553,
|
||||
"Y": 4.9015007,
|
||||
"Z": 39.29553
|
||||
}
|
||||
},
|
||||
"sky": {
|
||||
"username": "sky",
|
||||
"color": "purple",
|
||||
"position": {
|
||||
"X": 3.9765263,
|
||||
"Y": -5.033655,
|
||||
"Z": 19.824585
|
||||
"X": 5.9400105,
|
||||
"Y": -0.055064563,
|
||||
"Z": -3.896852
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"username": "test",
|
||||
"color": "red",
|
||||
"position": {
|
||||
"X": 14.141681,
|
||||
"Y": 2.2383373,
|
||||
"Z": -0.06184849
|
||||
"X": 2.1930797,
|
||||
"Y": -0.08324346,
|
||||
"Z": -1.550154
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user