package main import ( "log" "net" "time" pb "gitea.boner.be/bdnugget/goonserver/actions" rl "github.com/gen2brain/raylib-go/raylib" "google.golang.org/protobuf/proto" ) func ConnectToServer() (net.Conn, int32, error) { // Attempt to connect to the server conn, err := net.Dial("tcp", serverAddr) if err != nil { log.Printf("Failed to dial server: %v", err) return nil, 0, err } log.Println("Connected to server. Waiting for player ID...") // Buffer for incoming server message buf := make([]byte, 1024) n, err := conn.Read(buf) if err != nil { log.Printf("Error reading player ID from server: %v", err) return nil, 0, err } log.Printf("Received data: %x", buf[:n]) // Unmarshal server message to extract the player ID var response pb.ServerMessage if err := proto.Unmarshal(buf[:n], &response); err != nil { log.Printf("Failed to unmarshal server response: %v", err) return nil, 0, err } playerID := response.GetPlayerId() log.Printf("Successfully connected with player ID: %d", playerID) return conn, playerID, nil } func HandleServerCommunication(conn net.Conn, playerID int32, player *Player, otherPlayers map[int32]*Player) { // Goroutine to handle sending player's actions to the server go func() { for { if len(player.ActionQueue) > 0 { // Process the first action in the queue actionData := player.ActionQueue[0] action := &pb.Action{ PlayerId: playerID, Type: pb.Action_MOVE, X: int32(actionData.X), Y: int32(actionData.Y), } // Serialize the action data, err := proto.Marshal(action) if err != nil { log.Printf("Failed to marshal action: %v", err) continue } // Send action to server _, err = conn.Write(data) if err != nil { log.Printf("Failed to send action to server: %v", err) return } // Remove the action from the queue once it's sent player.ActionQueue = player.ActionQueue[1:] } // Add a delay to match the server's tick rate time.Sleep(TickRate) } }() // 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) return } var serverMessage pb.ServerMessage if err := proto.Unmarshal(buf[:n], &serverMessage); err != nil { log.Printf("Failed to unmarshal server message: %v", err) continue } // Update other players' states for _, state := range serverMessage.Players { if state.PlayerId != playerID { if otherPlayer, exists := otherPlayers[state.PlayerId]; exists { otherPlayer.PosTile = Tile{X: int(state.X), Y: int(state.Y)} otherPlayer.PosActual = rl.Vector3{ X: float32(state.X * TileSize), Y: float32(state.Y * TileHeight), Z: float32(state.Y * TileSize), } otherPlayer.MoveTowards(Tile{X: int(state.X), Y: int(state.Y)}, 0) } else { otherPlayers[state.PlayerId] = &Player{ PosTile: Tile{X: int(state.X), Y: int(state.Y)}, PosActual: rl.Vector3{ X: float32(state.X * TileSize), Y: float32(state.Y * TileHeight), Z: float32(state.Y * TileSize), }, ID: state.PlayerId, } } } } } }