From e5df746e7f265607f5b39613117111fe0e1ff01b Mon Sep 17 00:00:00 2001 From: Beric Bearnson <37596980+bericyb@users.noreply.github.com> Date: Fri, 23 Aug 2024 11:59:19 -0600 Subject: [PATCH] working lobby-ish --- cmd/client/main.go | 7 ++- cmd/server/main.go | 2 +- internal/client/client_utils.go | 11 +++-- internal/netwrk/game.go | 14 +----- internal/netwrk/lobby.go | 80 ++++++++++++++++++++++++++------- internal/netwrk/netwrk.go | 15 +++++++ 6 files changed, 94 insertions(+), 35 deletions(-) diff --git a/cmd/client/main.go b/cmd/client/main.go index 6bd00ac..b568b99 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -25,7 +25,7 @@ func main() { if err != nil { log.Panic("Bro your input is no good...") } - username := string(buf[:n]) + username := string(buf[:n-1]) conn, err := netwrk.ConnectToLobby(username) if err != nil { @@ -43,6 +43,9 @@ func main() { } userMessage, err := client.HandleUserInput(buf[:n]) + if err == io.EOF { + exit <- true + } if err != nil { fmt.Println(err) continue @@ -88,7 +91,7 @@ func main() { if err == io.EOF { log.Panic("Server disconnected sorry...") } else if err != nil { - log.Panic("Error reading from server connection...") + log.Panic("Error reading from server connection...", err) } message := &netwrk.LobbyMessage{} diff --git a/cmd/server/main.go b/cmd/server/main.go index 272af25..771c7dc 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -10,7 +10,7 @@ var exit chan bool func main() { fmt.Println("Starting sshpong server!") - netwrk.Listen() + netwrk.LobbyListen() _ = <-exit } diff --git a/internal/client/client_utils.go b/internal/client/client_utils.go index a05c920..d875c2c 100644 --- a/internal/client/client_utils.go +++ b/internal/client/client_utils.go @@ -8,9 +8,14 @@ import ( "strings" ) +var help = fmt.Errorf("use invite to invite a player\nchat or / to send a message to the lobby\nq or quit to leave the game") + func HandleUserInput(buf []byte) (*netwrk.LobbyMessage, error) { input := string(buf) args := strings.Fields(input) + if len(args) == 0 { + return nil, help + } switch args[0] { case "invite": if args[1] != "" { @@ -40,11 +45,11 @@ func HandleUserInput(buf []byte) (*netwrk.LobbyMessage, error) { case "q": return nil, io.EOF case "help": - return nil, fmt.Errorf("use invite to invite a player\nchat or / to send a message to the lobby\nq or quit to leave the game") + return nil, help case "h": - return nil, fmt.Errorf("use invite to invite a player\nchat or / to send a message to the lobby\nq or quit to leave the game") + return nil, help default: - return nil, fmt.Errorf("use invite to invite a player\nchat or / to send a message to the lobby\nq or quit to leave the game") + return nil, help } return nil, nil } diff --git a/internal/netwrk/game.go b/internal/netwrk/game.go index 9e3ec39..b1e2e8b 100644 --- a/internal/netwrk/game.go +++ b/internal/netwrk/game.go @@ -15,12 +15,12 @@ func handleGameConnection(conn net.Conn) { log.Printf("Error reading game ID on connection", err) } - gameID := string(messageBytes[:n]) + _ = string(messageBytes[:n]) if err != nil { log.Printf("Game id was not a string?", err) } - clientChan := make(chan GameMessage) + _ = make(chan GameMessage) n, err = conn.Read(messageBytes) if err != nil { @@ -28,16 +28,6 @@ func handleGameConnection(conn net.Conn) { return } - gameClients, ok := gameChans.games[gameID] - if !ok { - newGameClients := GameClients{ - client1: clientChan, - client2: nil, - } - gameChans.games[gameID] = newGameClients - } else { - gameClients.client2 = clientChan - } } func handleGameMessage(conn net.Conn, message *GameMessage) error { diff --git a/internal/netwrk/lobby.go b/internal/netwrk/lobby.go index 938caa3..603b450 100644 --- a/internal/netwrk/lobby.go +++ b/internal/netwrk/lobby.go @@ -9,8 +9,6 @@ import ( ) func handleLobbyConnection(conn net.Conn) { - defer conn.Close() - messageBytes := make([]byte, 4096) ingress := make(chan *LobbyMessage) @@ -21,9 +19,11 @@ func handleLobbyConnection(conn net.Conn) { for { n, err := conn.Read(messageBytes) if err == io.EOF { + conn.Close() return } if err != nil { + conn.Close() log.Printf("Error reading message %v", err) return } @@ -46,10 +46,15 @@ func handleLobbyConnection(conn net.Conn) { if err != nil { log.Println("Error marshalling message to send to user...", err) } + log.Println("sending message to user!") _, err = conn.Write(bytes) if err == io.EOF { + conn.Close() log.Println("User has disconnected", err) - ingress <- &LobbyMessage{Type: "disconnect"} + ingress <- &LobbyMessage{ + Type: "disconnect", + Content: msg.PlayerId, + } } if err != nil { log.Println("Error writing to user...", err) @@ -61,7 +66,7 @@ func handleLobbyConnection(conn net.Conn) { go func() { for { msg := <-ingress - serverMsg, err := handleClientLobbyMessage(msg) + serverMsg, err := handleClientLobbyMessage(msg, conn) if err != nil { log.Println("Error handling client lobby message...", err) } @@ -73,18 +78,29 @@ func handleLobbyConnection(conn net.Conn) { } // Returns a bool of whether the player has disconnected from the lobby and an error -func handleClientLobbyMessage(message *LobbyMessage) (*LobbyMessage, error) { +func handleClientLobbyMessage(message *LobbyMessage, conn net.Conn) (*LobbyMessage, error) { switch message.Type { + + // Handle an name/login message from a player + // Store the new player in the lobbyMembers + // Send a connection message for each of the lobbyMembers to the new player + // Send a connection message to all members in the lobby case "name": + log.Println("Got a name message!", message) _, ok := lobbyMembers.Load(message.Content) if ok { return &LobbyMessage{Type: "name_error", Content: "Sorry, that name is already taken, please try a different name"}, nil } username := message.Content + lobbyMembers.Store(username, Client{Username: username, Conn: conn}) + + log.Println("Storing new user!") // Send all client messages - lobbyMembers.Range(func(lobbyUsername string, client Client) bool { - externalMessageChan <- ExternalMessage{Target: username, Message: &LobbyMessage{Type: "connect", Content: lobbyUsername}} + lobbyMembers.Range(func(lobbyUsername any, client any) bool { + log.Println("ranging over users!") + usernameString, _ := lobbyUsername.(string) + externalMessageChan <- ExternalMessage{Target: username, Message: &LobbyMessage{Type: "connect", Content: usernameString}} return true }) @@ -93,44 +109,74 @@ func handleClientLobbyMessage(message *LobbyMessage) (*LobbyMessage, error) { broadcastToLobby(&LobbyMessage{PlayerId: "", Type: "connect", Content: username}) return &LobbyMessage{PlayerId: username, Type: "name", Content: username}, nil + + // Handle an invite message by sending a message to the target player + // Send an invite message to the invitee: message.Content + // Send an ack message to the inviter: message.PlayerId case "invite": - log.Println("Got invite for player:", message.Content) - invitee, ok := lobbyMembers[message.Content] - if !ok { - return &LobbyMessage{Type: "text", Content: "Sorry, that player is not available..."}, nil + externalMessageChan <- ExternalMessage{ + Target: message.Content, + Message: message, } + return &LobbyMessage{Type: "invite", Content: message.PlayerId}, nil + + // Handle a accept message from a player that was invited + // Send an ack message back to the player: message.PlayerId + // Send an invite ack message back to the inviter: message.Content case "accept_game": - player := lobbyMembers[message.Content] + externalMessageChan <- ExternalMessage{ + Target: message.Content, + Message: &LobbyMessage{Type: "accept", Content: ""}, + } return &LobbyMessage{Type: "accept", Content: ""}, nil + // Handle a chat message from a player with PlayerId case "chat": broadcastToLobby(&LobbyMessage{PlayerId: message.PlayerId, Type: "text", Content: message.Content}) return nil, nil + + // Handle a decline_game message from a player that was invited + // Send an ack message back to the invitee: message.PlayerId + // Send an ack message to the inviter: message.Content case "decline_game": - inviter := lobbyMembers[message.Content] + externalMessageChan <- ExternalMessage{ + Target: message.Content, + Message: &LobbyMessage{Type: "decline", Content: ""}, + } + return &LobbyMessage{Type: "decline_game", Content: message.PlayerId}, nil + + // Handle a quit message from a player that was connected + // broadcast the player quit to the lobby case "quit": - delete(lobbyMembers, message.PlayerId) + lobbyMembers.Delete(message.PlayerId) broadcastToLobby(&LobbyMessage{Type: "disconnect", Content: message.PlayerId}) return nil, nil + + // Ping and pong case "ping": return &LobbyMessage{Type: "pong", Content: "pong"}, nil + + // Ping and pong default: return &LobbyMessage{Type: "pong", Content: "pong"}, nil } } func broadcastToLobby(message *LobbyMessage) { - for _, player := range lobbyMembers { + lobbyMembers.Range(func(playerId, player interface{}) bool { bytes, err := proto.Marshal(message) if err != nil { log.Println("Error marshalling broadcast message", err) } - _, err = player.Conn.Write(bytes) + + client := player.(Client) + _, err = client.Conn.Write(bytes) if err != nil { log.Println("Error broadcasting to clients...", err) } - } + return true + }) } diff --git a/internal/netwrk/netwrk.go b/internal/netwrk/netwrk.go index 468ae7c..f733c23 100644 --- a/internal/netwrk/netwrk.go +++ b/internal/netwrk/netwrk.go @@ -4,6 +4,8 @@ import ( "log" "net" sync "sync" + + "google.golang.org/protobuf/proto" ) type Client struct { @@ -32,6 +34,19 @@ func init() { externalMessageChan = make(chan ExternalMessage) lobbyMembers = sync.Map{} + + go func() { + for { + msg := <-externalMessageChan + player, ok := lobbyMembers.Load(msg.Target) + if !ok { + continue + } + client, _ := player.(Client) + bytes, _ := proto.Marshal(msg.Message) + client.Conn.Write(bytes) + } + }() } // Starts listening on port 12345 for TCP connections