goonscape/network/network.go

241 lines
5.6 KiB
Go
Raw Normal View History

2025-01-13 11:10:48 +01:00
package network
2024-10-31 01:06:39 +01:00
import (
2025-01-15 10:50:51 +01:00
"bufio"
2025-02-14 13:35:09 +01:00
"context"
2025-01-15 10:50:51 +01:00
"encoding/binary"
2025-01-19 21:23:47 +01:00
"fmt"
2025-01-15 10:50:51 +01:00
"io"
2024-10-31 01:06:39 +01:00
"log"
"net"
2025-02-14 13:35:09 +01:00
"sync"
2024-10-31 01:06:39 +01:00
"time"
2025-02-14 13:35:09 +01:00
"gitea.boner.be/bdnugget/goonscape/logging"
2025-01-13 11:10:48 +01:00
"gitea.boner.be/bdnugget/goonscape/types"
2024-10-31 01:06:39 +01:00
pb "gitea.boner.be/bdnugget/goonserver/actions"
"google.golang.org/protobuf/proto"
)
const protoVersion = 1
var serverAddr = "boner.be:6969"
2025-02-14 13:35:09 +01:00
type NetworkManager struct {
ctx context.Context
conn net.Conn
reader *bufio.Reader
writer *bufio.Writer
mu sync.Mutex
}
func NewNetworkManager(ctx context.Context) *NetworkManager {
return &NetworkManager{
ctx: ctx,
}
}
func SetServerAddr(addr string) {
serverAddr = addr
}
2025-02-14 13:35:09 +01:00
func (nm *NetworkManager) Connect(addr string) error {
nm.mu.Lock()
defer nm.mu.Unlock()
var err error
nm.conn, err = net.Dial("tcp", addr)
if err != nil {
return err
}
nm.reader = bufio.NewReader(nm.conn)
nm.writer = bufio.NewWriter(nm.conn)
go nm.readLoop()
return nil
}
func (nm *NetworkManager) readLoop() {
for {
select {
case <-nm.ctx.Done():
return
default:
// Read and process messages
}
}
}
func (nm *NetworkManager) Send(message proto.Message) error {
nm.mu.Lock()
defer nm.mu.Unlock()
data, err := proto.Marshal(message)
if err != nil {
return err
}
// Write length prefix
lengthBuf := make([]byte, 4)
binary.BigEndian.PutUint32(lengthBuf, uint32(len(data)))
if _, err := nm.writer.Write(lengthBuf); err != nil {
return err
}
// Write message body
if _, err := nm.writer.Write(data); err != nil {
return err
}
return nm.writer.Flush()
}
2025-01-19 21:23:47 +01:00
func ConnectToServer(username, password string, isRegistering bool) (net.Conn, int32, error) {
2025-02-14 13:35:09 +01:00
logging.Info.Println("Attempting to connect to server at", serverAddr)
conn, err := net.Dial("tcp", serverAddr)
2024-10-31 01:06:39 +01:00
if err != nil {
2025-02-14 13:35:09 +01:00
logging.Error.Printf("Failed to dial server: %v", err)
2024-10-31 01:06:39 +01:00
return nil, 0, err
}
2025-02-14 13:35:09 +01:00
logging.Info.Println("Connected to server. Authenticating...")
2025-01-19 21:23:47 +01:00
// Send auth message
authAction := &pb.Action{
Type: pb.Action_LOGIN,
Username: username,
Password: password,
}
if isRegistering {
authAction.Type = pb.Action_REGISTER
}
authBatch := &pb.ActionBatch{
Actions: []*pb.Action{authAction},
ProtocolVersion: protoVersion,
2025-01-19 21:23:47 +01:00
}
if err := writeMessage(conn, authBatch); err != nil {
conn.Close()
return nil, 0, fmt.Errorf("failed to send auth: %v", err)
}
2025-01-15 10:58:11 +01:00
2025-01-19 21:23:47 +01:00
// Read server response
reader := bufio.NewReader(conn)
2025-01-15 10:58:11 +01:00
lengthBuf := make([]byte, 4)
if _, err := io.ReadFull(reader, lengthBuf); err != nil {
2025-01-19 21:23:47 +01:00
conn.Close()
return nil, 0, fmt.Errorf("failed to read auth response: %v", err)
2025-01-15 10:58:11 +01:00
}
messageLength := binary.BigEndian.Uint32(lengthBuf)
messageBuf := make([]byte, messageLength)
if _, err := io.ReadFull(reader, messageBuf); err != nil {
2025-01-19 21:23:47 +01:00
conn.Close()
return nil, 0, fmt.Errorf("failed to read auth response body: %v", err)
2024-10-31 01:06:39 +01:00
}
var response pb.ServerMessage
2025-01-15 10:58:11 +01:00
if err := proto.Unmarshal(messageBuf, &response); err != nil {
2025-01-19 21:23:47 +01:00
conn.Close()
return nil, 0, fmt.Errorf("failed to unmarshal auth response: %v", err)
}
if response.ProtocolVersion > protoVersion {
conn.Close()
return nil, 0, fmt.Errorf("server requires newer protocol version (server: %d, client: %d)",
response.ProtocolVersion, protoVersion)
}
2025-01-19 21:23:47 +01:00
if !response.AuthSuccess {
conn.Close()
2025-02-14 13:35:09 +01:00
return nil, 0, fmt.Errorf("authentication failed: %s", response.ErrorMessage)
2024-10-31 01:06:39 +01:00
}
playerID := response.GetPlayerId()
2025-01-19 21:23:47 +01:00
log.Printf("Successfully authenticated with player ID: %d", playerID)
2024-10-31 01:06:39 +01:00
return conn, playerID, nil
}
2025-02-14 13:35:09 +01:00
func HandleServerCommunication(conn net.Conn, playerID int32, player *types.Player, otherPlayers *sync.Map, quitChan <-chan struct{}) {
defer func() {
logging.Info.Println("Closing connection and cleaning up for player", playerID)
conn.Close()
close(player.QuitDone)
2024-10-31 01:06:39 +01:00
}()
2025-02-14 13:35:09 +01:00
reader := bufio.NewReader(conn)
ticker := time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-quitChan:
return
2025-02-14 13:35:09 +01:00
case <-ticker.C:
// Read message length
lengthBuf := make([]byte, 4)
if _, err := io.ReadFull(reader, lengthBuf); err != nil {
log.Printf("Failed to read message length: %v", err)
2025-02-14 13:35:09 +01:00
continue
}
messageLength := binary.BigEndian.Uint32(lengthBuf)
2025-01-15 10:50:51 +01:00
2025-02-14 13:35:09 +01:00
// Read message body
messageBuf := make([]byte, messageLength)
if _, err := io.ReadFull(reader, messageBuf); err != nil {
log.Printf("Failed to read message body: %v", err)
2025-02-14 13:35:09 +01:00
continue
}
2024-10-31 01:06:39 +01:00
2025-02-14 13:35:09 +01:00
// Process server message
var serverMessage pb.ServerMessage
if err := proto.Unmarshal(messageBuf, &serverMessage); err != nil {
log.Printf("Failed to unmarshal server message: %v", err)
continue
}
2024-10-31 01:06:39 +01:00
2025-02-14 13:35:09 +01:00
// Update player states
for _, state := range serverMessage.Players {
2025-02-14 13:35:09 +01:00
if state == nil {
logging.Error.Println("Received nil player state")
continue
2025-01-13 10:00:23 +01:00
}
2025-01-13 00:31:15 +01:00
2025-02-14 13:35:09 +01:00
if state.PlayerId == playerID {
player.UpdatePosition(state, types.ServerTickRate)
} else if existing, ok := otherPlayers.Load(state.PlayerId); ok {
existing.(*types.Player).UpdatePosition(state, types.ServerTickRate)
} else {
2025-02-14 13:35:09 +01:00
newPlayer := types.NewPlayer(state)
otherPlayers.Store(state.PlayerId, newPlayer)
2025-01-20 00:03:50 +01:00
}
}
2025-02-14 13:35:09 +01:00
// Handle chat messages
if handler, ok := player.UserData.(types.ChatMessageHandler); ok {
handler.HandleServerMessages(serverMessage.ChatMessages)
}
2024-10-31 01:06:39 +01:00
}
}
}
2025-01-15 10:50:51 +01:00
// Helper function to write length-prefixed messages
func writeMessage(conn net.Conn, msg proto.Message) error {
data, err := proto.Marshal(msg)
if err != nil {
return err
}
// Write length prefix
lengthBuf := make([]byte, 4)
binary.BigEndian.PutUint32(lengthBuf, uint32(len(data)))
if _, err := conn.Write(lengthBuf); err != nil {
return err
}
// Write message body
_, err = conn.Write(data)
return err
}