Only send/recieve new unread chat messages instead of spamming entire bandwidth
This commit is contained in:
parent
555b8118f2
commit
b866ac879e
@ -1 +1 @@
|
|||||||
Subproject commit f9ec811b10bbab54e843199eb68156e9e7c143cc
|
Subproject commit c720b668180d46b8eb37747f9c24d2fa1f49de72
|
@ -19,6 +19,7 @@ import (
|
|||||||
const protoVersion = 1
|
const protoVersion = 1
|
||||||
|
|
||||||
var serverAddr = "boner.be:6969" // Default server address
|
var serverAddr = "boner.be:6969" // Default server address
|
||||||
|
var lastSeenMessageTimestamp int64 = 0 // Track the last message timestamp seen by this client
|
||||||
|
|
||||||
func SetServerAddr(addr string) {
|
func SetServerAddr(addr string) {
|
||||||
serverAddr = addr
|
serverAddr = addr
|
||||||
@ -26,10 +27,32 @@ func SetServerAddr(addr string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ConnectToServer(username, password string, isRegistering bool) (net.Conn, int32, error) {
|
func ConnectToServer(username, password string, isRegistering bool) (net.Conn, int32, error) {
|
||||||
conn, err := net.Dial("tcp", serverAddr)
|
log.Printf("Connecting to server at %s...", serverAddr)
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed to dial server: %v", err)
|
var err error
|
||||||
return nil, 0, err
|
var conn net.Conn
|
||||||
|
|
||||||
|
// Try connecting with a timeout
|
||||||
|
connChan := make(chan net.Conn, 1)
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
c, e := net.Dial("tcp", serverAddr)
|
||||||
|
if e != nil {
|
||||||
|
errChan <- e
|
||||||
|
return
|
||||||
|
}
|
||||||
|
connChan <- c
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Wait for connection with timeout
|
||||||
|
select {
|
||||||
|
case conn = <-connChan:
|
||||||
|
// Connection successful, continue
|
||||||
|
case err = <-errChan:
|
||||||
|
return nil, 0, fmt.Errorf("failed to dial server: %v", err)
|
||||||
|
case <-time.After(5 * time.Second):
|
||||||
|
return nil, 0, fmt.Errorf("connection timeout after 5 seconds")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Connected to server. Authenticating...")
|
log.Println("Connected to server. Authenticating...")
|
||||||
@ -54,8 +77,12 @@ func ConnectToServer(username, password string, isRegistering bool) (net.Conn, i
|
|||||||
return nil, 0, fmt.Errorf("failed to send auth: %v", err)
|
return nil, 0, fmt.Errorf("failed to send auth: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read server response
|
// Read server response with timeout
|
||||||
reader := bufio.NewReader(conn)
|
reader := bufio.NewReader(conn)
|
||||||
|
|
||||||
|
// Set a read deadline for authentication
|
||||||
|
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||||
|
|
||||||
lengthBuf := make([]byte, 4)
|
lengthBuf := make([]byte, 4)
|
||||||
if _, err := io.ReadFull(reader, lengthBuf); err != nil {
|
if _, err := io.ReadFull(reader, lengthBuf); err != nil {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
@ -63,12 +90,21 @@ func ConnectToServer(username, password string, isRegistering bool) (net.Conn, i
|
|||||||
}
|
}
|
||||||
messageLength := binary.BigEndian.Uint32(lengthBuf)
|
messageLength := binary.BigEndian.Uint32(lengthBuf)
|
||||||
|
|
||||||
|
// Sanity check message size
|
||||||
|
if messageLength > 1024*1024 { // 1MB max message size
|
||||||
|
conn.Close()
|
||||||
|
return nil, 0, fmt.Errorf("authentication response too large: %d bytes", messageLength)
|
||||||
|
}
|
||||||
|
|
||||||
messageBuf := make([]byte, messageLength)
|
messageBuf := make([]byte, messageLength)
|
||||||
if _, err := io.ReadFull(reader, messageBuf); err != nil {
|
if _, err := io.ReadFull(reader, messageBuf); err != nil {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return nil, 0, fmt.Errorf("failed to read auth response body: %v", err)
|
return nil, 0, fmt.Errorf("failed to read auth response body: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear read deadline after authentication
|
||||||
|
conn.SetReadDeadline(time.Time{})
|
||||||
|
|
||||||
var response pb.ServerMessage
|
var response pb.ServerMessage
|
||||||
if err := proto.Unmarshal(messageBuf, &response); err != nil {
|
if err := proto.Unmarshal(messageBuf, &response); err != nil {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
@ -88,6 +124,10 @@ func ConnectToServer(username, password string, isRegistering bool) (net.Conn, i
|
|||||||
|
|
||||||
playerID := response.GetPlayerId()
|
playerID := response.GetPlayerId()
|
||||||
log.Printf("Successfully authenticated with player ID: %d", playerID)
|
log.Printf("Successfully authenticated with player ID: %d", playerID)
|
||||||
|
|
||||||
|
// Reset the lastSeenMessageTimestamp when reconnecting
|
||||||
|
lastSeenMessageTimestamp = 0
|
||||||
|
|
||||||
return conn, playerID, nil
|
return conn, playerID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +150,12 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *types.Play
|
|||||||
errChan := make(chan error, 1)
|
errChan := make(chan error, 1)
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
|
||||||
|
// Add a heartbeat ticker to detect connection issues
|
||||||
|
heartbeatTicker := time.NewTicker(5 * time.Second)
|
||||||
|
defer heartbeatTicker.Stop()
|
||||||
|
|
||||||
|
lastMessageTime := time.Now()
|
||||||
|
|
||||||
// Start message sending goroutine
|
// Start message sending goroutine
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -135,6 +181,22 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *types.Play
|
|||||||
return
|
return
|
||||||
case <-done:
|
case <-done:
|
||||||
return
|
return
|
||||||
|
case <-heartbeatTicker.C:
|
||||||
|
// If no message has been sent for a while, send a heartbeat
|
||||||
|
timeSinceLastMessage := time.Since(lastMessageTime)
|
||||||
|
if timeSinceLastMessage > 5*time.Second {
|
||||||
|
// Send an empty batch as a heartbeat
|
||||||
|
emptyBatch := &pb.ActionBatch{
|
||||||
|
PlayerId: playerID,
|
||||||
|
LastSeenMessageTimestamp: lastSeenMessageTimestamp,
|
||||||
|
}
|
||||||
|
if err := writeMessage(conn, emptyBatch); err != nil {
|
||||||
|
log.Printf("Failed to send heartbeat: %v", err)
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastMessageTime = time.Now()
|
||||||
|
}
|
||||||
case <-actionTicker.C:
|
case <-actionTicker.C:
|
||||||
player.Lock()
|
player.Lock()
|
||||||
if len(player.ActionQueue) > 0 {
|
if len(player.ActionQueue) > 0 {
|
||||||
@ -144,6 +206,7 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *types.Play
|
|||||||
PlayerId: playerID,
|
PlayerId: playerID,
|
||||||
Actions: actions,
|
Actions: actions,
|
||||||
Tick: player.CurrentTick,
|
Tick: player.CurrentTick,
|
||||||
|
LastSeenMessageTimestamp: lastSeenMessageTimestamp,
|
||||||
}
|
}
|
||||||
player.ActionQueue = player.ActionQueue[:0]
|
player.ActionQueue = player.ActionQueue[:0]
|
||||||
player.Unlock()
|
player.Unlock()
|
||||||
@ -152,6 +215,7 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *types.Play
|
|||||||
errChan <- err
|
errChan <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
lastMessageTime = time.Now()
|
||||||
} else {
|
} else {
|
||||||
player.Unlock()
|
player.Unlock()
|
||||||
}
|
}
|
||||||
@ -260,6 +324,13 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *types.Play
|
|||||||
if handler, ok := player.UserData.(types.ChatMessageHandler); ok && len(serverMessage.ChatMessages) > 0 {
|
if handler, ok := player.UserData.(types.ChatMessageHandler); ok && len(serverMessage.ChatMessages) > 0 {
|
||||||
log.Printf("Received %d chat messages from server", len(serverMessage.ChatMessages))
|
log.Printf("Received %d chat messages from server", len(serverMessage.ChatMessages))
|
||||||
handler.HandleServerMessages(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]
|
||||||
|
lastSeenMessageTimestamp = lastMsg.Timestamp
|
||||||
|
log.Printf("Updated last seen message timestamp to %d", lastSeenMessageTimestamp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,6 +339,7 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *types.Play
|
|||||||
// Wait for error or quit signal
|
// Wait for error or quit signal
|
||||||
select {
|
select {
|
||||||
case <-quitChan:
|
case <-quitChan:
|
||||||
|
log.Printf("Received quit signal, sending disconnect message")
|
||||||
// Send disconnect message
|
// Send disconnect message
|
||||||
disconnectMsg := &pb.ActionBatch{
|
disconnectMsg := &pb.ActionBatch{
|
||||||
PlayerId: playerID,
|
PlayerId: playerID,
|
||||||
@ -277,8 +349,10 @@ func HandleServerCommunication(conn net.Conn, playerID int32, player *types.Play
|
|||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
writeMessage(conn, disconnectMsg)
|
writeMessage(conn, disconnectMsg)
|
||||||
|
close(done)
|
||||||
case err := <-errChan:
|
case err := <-errChan:
|
||||||
log.Printf("Network error: %v", err)
|
log.Printf("Network error: %v", err)
|
||||||
|
close(done)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user