networking protocol refactor
This commit is contained in:
		
							parent
							
								
									a97bd301d5
								
							
						
					
					
						commit
						15e7f20f1a
					
				@ -21,8 +21,8 @@ func main() {
 | 
				
			|||||||
	fmt.Println("Welcome to sshpong!")
 | 
						fmt.Println("Welcome to sshpong!")
 | 
				
			||||||
	fmt.Println("Please enter your username")
 | 
						fmt.Println("Please enter your username")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	egress := make(chan lobby.LobbyMessage)
 | 
						egress := make(chan []byte)
 | 
				
			||||||
	ingress := make(chan lobby.LobbyMessage)
 | 
						ingress := make(chan []byte)
 | 
				
			||||||
	interrupter := make(chan client.InterrupterMessage, 100)
 | 
						interrupter := make(chan client.InterrupterMessage, 100)
 | 
				
			||||||
	exit := make(chan string)
 | 
						exit := make(chan string)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -40,7 +40,7 @@ func main() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// User input handler
 | 
						// User input handler
 | 
				
			||||||
	go func(egress chan lobby.LobbyMessage) {
 | 
						go func() {
 | 
				
			||||||
		buf := make([]byte, 1024)
 | 
							buf := make([]byte, 1024)
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			n, err := os.Stdin.Read(buf)
 | 
								n, err := os.Stdin.Read(buf)
 | 
				
			||||||
@ -51,7 +51,7 @@ func main() {
 | 
				
			|||||||
			input := string(buf[:n-1])
 | 
								input := string(buf[:n-1])
 | 
				
			||||||
			args := strings.Fields(input)
 | 
								args := strings.Fields(input)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			userMessage := lobby.LobbyMessage{}
 | 
								userMessage := []byte{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			select {
 | 
								select {
 | 
				
			||||||
			case msg := <-interrupter:
 | 
								case msg := <-interrupter:
 | 
				
			||||||
@ -67,20 +67,14 @@ func main() {
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				egress <- userMessage
 | 
									egress <- userMessage
 | 
				
			||||||
				if userMessage.MessageType == "accept" || userMessage.MessageType == "disconect" {
 | 
									if userMessage[0] == lobby.Accept || userMessage[0] == lobby.Disconnect {
 | 
				
			||||||
					slog.Debug("Closing input handler with accept or disconnect message", slog.Any("message content", userMessage.Message))
 | 
										slog.Debug("Closing input handler with accept or disconnect message")
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if userMessage.MessageType == "start_game" {
 | 
									if userMessage[0] == lobby.StartGame {
 | 
				
			||||||
					slog.Debug("closing input handler with start_game message and sending exit signal")
 | 
										slog.Debug("closing input handler with start_game message and sending exit signal")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					// TODO: This is a wierd one...
 | 
										exit <- msg.Content
 | 
				
			||||||
					sg, ok := userMessage.Message.(lobby.StartGame)
 | 
					 | 
				
			||||||
					if !ok {
 | 
					 | 
				
			||||||
						slog.Debug("Start game interrupt message was improperly formatted... Could be indicative of an error in the HandleinterruptInput method")
 | 
					 | 
				
			||||||
						continue
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					exit <- sg.GameID
 | 
					 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -98,10 +92,10 @@ func main() {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}(egress)
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ingress Handler
 | 
						// Ingress Handler
 | 
				
			||||||
	go func(oc chan lobby.LobbyMessage) {
 | 
						go func() {
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			msg := <-ingress
 | 
								msg := <-ingress
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -114,47 +108,36 @@ func main() {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}(ingress)
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Network writer
 | 
						// Network writer
 | 
				
			||||||
	go func(userMessages chan lobby.LobbyMessage) {
 | 
						go func() {
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			msg := <-userMessages
 | 
								msg := <-egress
 | 
				
			||||||
			bytes, err := lobby.Marshal(msg)
 | 
								slog.Debug("writing egress message to server", "message", msg)
 | 
				
			||||||
			if err != nil {
 | 
					
 | 
				
			||||||
				log.Panic("Malformed proto message", err)
 | 
								_, err = conn.Write(msg)
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			_, err = conn.Write(bytes)
 | 
					 | 
				
			||||||
			if err == io.EOF {
 | 
								if err == io.EOF {
 | 
				
			||||||
				log.Panic("Server disconnected sorry...")
 | 
									log.Panic("Server disconnected, sorry...")
 | 
				
			||||||
			} else if err != nil {
 | 
					 | 
				
			||||||
				log.Panic("Error reading from server connection...")
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if msg.MessageType == "start_game" || msg.MessageType == "disconnect" {
 | 
								if msg[0] == lobby.StartGame || msg[0] == lobby.Disconnect {
 | 
				
			||||||
				slog.Debug("closing network writer ")
 | 
									slog.Debug("closing network writer ")
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}(egress)
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Network reader
 | 
						// Network reader
 | 
				
			||||||
	go func(serverMessages chan lobby.LobbyMessage) {
 | 
						go func() {
 | 
				
			||||||
		buf := make([]byte, 1024)
 | 
							buf := make([]byte, 1024)
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			n, err := conn.Read(buf)
 | 
								n, err := conn.Read(buf)
 | 
				
			||||||
			if err == io.EOF {
 | 
								if err == io.EOF {
 | 
				
			||||||
				fmt.Println("disconnected from lobby")
 | 
									log.Panic("disconnected from lobby")
 | 
				
			||||||
			} else if err != nil {
 | 
					 | 
				
			||||||
				log.Panic("Error reading from server connection...", err)
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								ingress <- buf[:n]
 | 
				
			||||||
			message, err := lobby.Unmarshal(buf[:n])
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				log.Panic("Error reading message from server", err)
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
			serverMessages <- message
 | 
						}()
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}(ingress)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fmt.Println("Waiting for an exit message")
 | 
						fmt.Println("Waiting for an exit message")
 | 
				
			||||||
	isStartGame := <-exit
 | 
						isStartGame := <-exit
 | 
				
			||||||
@ -179,7 +162,7 @@ func ConnectToLobby(username string) (net.Conn, error) {
 | 
				
			|||||||
		return nil, fmt.Errorf("Sorry, failed to connect to server...")
 | 
							return nil, fmt.Errorf("Sorry, failed to connect to server...")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	loginMsg, err := lobby.Marshal(lobby.LobbyMessage{MessageType: "name", Message: lobby.Name{Name: username}})
 | 
						loginMsg, err := lobby.Marshal(lobby.NameData{Name: username}, lobby.Name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("Sorry bro but your username is wack AF...")
 | 
							return nil, fmt.Errorf("Sorry bro but your username is wack AF...")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,23 @@ func LobbyListen() {
 | 
				
			|||||||
			log.Println(err)
 | 
								log.Println(err)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		go l.HandleLobbyConnection(conn)
 | 
					
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								client, msgOut := l.InitialConnectionHandler(conn)
 | 
				
			||||||
 | 
								_, err = conn.Write(msgOut)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									slog.Debug("error writing to new player... disconnecting")
 | 
				
			||||||
 | 
									msg, err := lobby.Marshal(lobby.DisconnectData{
 | 
				
			||||||
 | 
										From: client.Username,
 | 
				
			||||||
 | 
									}, lobby.Disconnect)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										slog.Error("error marshalling disconnect message on player connect")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									l.BroadcastToLobby(msg)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								go l.HandleLobbyConnection(client)
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -19,121 +19,116 @@ var help = fmt.Errorf("use invite <player name> to invite a player\nchat or / to
 | 
				
			|||||||
var red = "\x1b[31m"
 | 
					var red = "\x1b[31m"
 | 
				
			||||||
var normal = "\033[0m"
 | 
					var normal = "\033[0m"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func HandleUserInput(args []string, username string) (lobby.LobbyMessage, error) {
 | 
					func HandleUserInput(args []string, username string) ([]byte, error) {
 | 
				
			||||||
	if len(args) == 0 {
 | 
						if len(args) == 0 {
 | 
				
			||||||
		return lobby.LobbyMessage{}, help
 | 
							return []byte{}, help
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	switch args[0] {
 | 
						switch args[0] {
 | 
				
			||||||
	case "invite":
 | 
						case "invite":
 | 
				
			||||||
		if args[1] != "" {
 | 
							if args[1] != "" {
 | 
				
			||||||
			return lobby.LobbyMessage{
 | 
								msg, err := lobby.Marshal(lobby.InviteData{From: username, To: args[1]}, lobby.Invite)
 | 
				
			||||||
				MessageType: "invite",
 | 
								if err != nil {
 | 
				
			||||||
				Message:     lobby.Invite{From: username, To: args[1]}}, nil
 | 
									slog.Debug("invite message was not properly marshalled", "error", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return msg, err
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			fmt.Println("Please provide a player to invite ")
 | 
								fmt.Println("Please provide a player to invite ")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case "chat":
 | 
						case "chat":
 | 
				
			||||||
		if args[1] != "" {
 | 
							if args[1] != "" {
 | 
				
			||||||
			return lobby.LobbyMessage{
 | 
								msg, err := lobby.Marshal(lobby.ChatData{
 | 
				
			||||||
				MessageType: "chat",
 | 
					 | 
				
			||||||
				Message: lobby.Chat{
 | 
					 | 
				
			||||||
				From:    username,
 | 
									From:    username,
 | 
				
			||||||
					Message: args[1],
 | 
									Message: strings.Join(args[1:], " "),
 | 
				
			||||||
				},
 | 
								}, lobby.Chat)
 | 
				
			||||||
			}, nil
 | 
								if err != nil {
 | 
				
			||||||
 | 
									slog.Debug("chat message was not properly marshalled", "error", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return msg, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case "/":
 | 
						case "/":
 | 
				
			||||||
		if args[1] != "" {
 | 
							if args[1] != "" {
 | 
				
			||||||
			return lobby.LobbyMessage{
 | 
								msg, err := lobby.Marshal(lobby.ChatData{
 | 
				
			||||||
				MessageType: "chat",
 | 
					 | 
				
			||||||
				Message: lobby.Chat{
 | 
					 | 
				
			||||||
				From:    username,
 | 
									From:    username,
 | 
				
			||||||
					Message: args[1],
 | 
									Message: strings.Join(args[1:], " "),
 | 
				
			||||||
				},
 | 
								}, lobby.Chat)
 | 
				
			||||||
			}, nil
 | 
								if err != nil {
 | 
				
			||||||
 | 
									slog.Debug("chat slash message was not properly marshalled", "error", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return msg, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case "quit":
 | 
						case "quit":
 | 
				
			||||||
		return lobby.LobbyMessage{}, io.EOF
 | 
							return []byte{}, io.EOF
 | 
				
			||||||
	case "q":
 | 
						case "q":
 | 
				
			||||||
		return lobby.LobbyMessage{}, io.EOF
 | 
							return []byte{}, io.EOF
 | 
				
			||||||
	case "help":
 | 
						case "help":
 | 
				
			||||||
		return lobby.LobbyMessage{}, help
 | 
							return []byte{}, help
 | 
				
			||||||
	case "h":
 | 
						case "h":
 | 
				
			||||||
		return lobby.LobbyMessage{}, help
 | 
							return []byte{}, help
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		if strings.Index(args[0], "/") == 0 {
 | 
							if strings.Index(args[0], "/") == 0 {
 | 
				
			||||||
			return lobby.LobbyMessage{
 | 
								msg, err := lobby.Marshal(lobby.ChatData{
 | 
				
			||||||
				MessageType: "chat",
 | 
					 | 
				
			||||||
				Message: lobby.Chat{
 | 
					 | 
				
			||||||
				From:    username,
 | 
									From:    username,
 | 
				
			||||||
					Message: args[1],
 | 
									Message: strings.Join(args, " ")[1:],
 | 
				
			||||||
				},
 | 
								}, lobby.Chat)
 | 
				
			||||||
			}, nil
 | 
								if err != nil {
 | 
				
			||||||
 | 
									slog.Debug("chat slash default message was not properly marshalled", "error", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		return lobby.LobbyMessage{}, help
 | 
								return msg, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	return lobby.LobbyMessage{}, nil
 | 
							return []byte{}, help
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return []byte{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func HandleInterruptInput(incoming InterrupterMessage, args []string, username string) (lobby.LobbyMessage, error) {
 | 
					func HandleInterruptInput(incoming InterrupterMessage, args []string, username string) ([]byte, error) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch incoming.InterruptType {
 | 
						switch incoming.InterruptType {
 | 
				
			||||||
 | 
						// Respond with yes if you accept game
 | 
				
			||||||
	case "invite":
 | 
						case "invite":
 | 
				
			||||||
		if len(args) < 1 {
 | 
							if len(args) < 1 {
 | 
				
			||||||
			return lobby.LobbyMessage{
 | 
								return []byte{}, nil
 | 
				
			||||||
				MessageType: "decline",
 | 
					 | 
				
			||||||
				Message: lobby.Decline{
 | 
					 | 
				
			||||||
					From: username,
 | 
					 | 
				
			||||||
					To:   incoming.Content,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			}, nil
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			if strings.ToLower(args[0]) == "y" || strings.ToLower(args[0]) == "yes" {
 | 
								if strings.ToLower(args[0]) == "y" || strings.ToLower(args[0]) == "yes" {
 | 
				
			||||||
				return lobby.LobbyMessage{MessageType: "accept", Message: lobby.Accept{
 | 
									msg, err := lobby.Marshal(lobby.AcceptData{
 | 
				
			||||||
					From: username,
 | 
										From: username,
 | 
				
			||||||
					To:   incoming.Content,
 | 
										To:   incoming.Content,
 | 
				
			||||||
				},
 | 
									}, lobby.Accept)
 | 
				
			||||||
				}, nil
 | 
									if err != nil {
 | 
				
			||||||
 | 
										slog.Debug("accept message was not properly marshalled", "error", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return msg, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// // Cancel waiting for invite? we aren't doing this I guess.
 | 
					 | 
				
			||||||
	// case "decline":
 | 
					 | 
				
			||||||
	// 	return nil,
 | 
					 | 
				
			||||||
	// Disconnect and connect to game
 | 
						// Disconnect and connect to game
 | 
				
			||||||
	case "accepted":
 | 
						case "accepted":
 | 
				
			||||||
		return lobby.LobbyMessage{
 | 
							msg, err := lobby.Marshal(lobby.DisconnectData{
 | 
				
			||||||
			MessageType: "disconnect",
 | 
					 | 
				
			||||||
			Message: lobby.Disconnect{
 | 
					 | 
				
			||||||
			From: incoming.Content,
 | 
								From: incoming.Content,
 | 
				
			||||||
			},
 | 
							}, lobby.Disconnect)
 | 
				
			||||||
		}, nil
 | 
							if err != nil {
 | 
				
			||||||
 | 
								slog.Debug("disconnect message was not properly marshalled", "error", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return msg, err
 | 
				
			||||||
	case "start_game":
 | 
						case "start_game":
 | 
				
			||||||
		return lobby.LobbyMessage{
 | 
							msg, err := lobby.Marshal(lobby.StartGameData{
 | 
				
			||||||
			MessageType: "start_game",
 | 
								To:     "",
 | 
				
			||||||
			Message:     lobby.StartGame{GameID: incoming.Content},
 | 
								GameID: incoming.Content,
 | 
				
			||||||
		}, nil
 | 
							}, lobby.Chat)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								slog.Debug("start game message was not properly marshalled", "error", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return msg, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return lobby.LobbyMessage{}, fmt.Errorf("received a interrupt message that could not be handled %v", incoming)
 | 
						return []byte{}, fmt.Errorf("received a interrupt message that could not be handled %v", incoming)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func HandleServerMessage(message lobby.LobbyMessage) (InterrupterMessage, error) {
 | 
					func HandleServerMessage(msg []byte) (InterrupterMessage, error) {
 | 
				
			||||||
 | 
						header := msg[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	msg := message.Message
 | 
						switch header {
 | 
				
			||||||
	switch message.MessageType {
 | 
						case lobby.Invite:
 | 
				
			||||||
	case "name":
 | 
							imsg, err := lobby.Unmarshal[lobby.InviteData](msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
		nmsg, ok := msg.(lobby.Name)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return InterrupterMessage{}, errors.New("Not a properly formatted name message")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		fmt.Printf("Current Players\n%s\n", nmsg)
 | 
					 | 
				
			||||||
	case "invite":
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		imsg, ok := msg.(lobby.Invite)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return InterrupterMessage{}, errors.New("Not a propertly formatted invite message")
 | 
								return InterrupterMessage{}, errors.New("Not a propertly formatted invite message")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fmt.Println(imsg.From, "is inviting you to a game\nType y to accept...")
 | 
							fmt.Println(imsg.From, "is inviting you to a game\nType y to accept...")
 | 
				
			||||||
@ -141,17 +136,17 @@ func HandleServerMessage(message lobby.LobbyMessage) (InterrupterMessage, error)
 | 
				
			|||||||
			InterruptType: "invite",
 | 
								InterruptType: "invite",
 | 
				
			||||||
			Content:       imsg.From,
 | 
								Content:       imsg.From,
 | 
				
			||||||
		}, nil
 | 
							}, nil
 | 
				
			||||||
	case "pending_invite":
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pimsg, ok := msg.(lobby.PendingInvite)
 | 
						case lobby.PendingInvite:
 | 
				
			||||||
		if !ok {
 | 
							pimsg, err := lobby.Unmarshal[lobby.PendingInviteData](msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
			return InterrupterMessage{}, errors.New("Not a properly formatted pending invite message")
 | 
								return InterrupterMessage{}, errors.New("Not a properly formatted pending invite message")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fmt.Println("Invite sent to", pimsg.Recipient, "\nWaiting for response...")
 | 
							fmt.Println("Invite sent to", pimsg.Recipient, "\nWaiting for response...")
 | 
				
			||||||
	case "accepted":
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		amsg, ok := msg.(lobby.Accepted)
 | 
						case lobby.Accepted:
 | 
				
			||||||
		if !ok {
 | 
							amsg, err := lobby.Unmarshal[lobby.AcceptedData](msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
			return InterrupterMessage{}, errors.New("Not a properly formatted accepted message")
 | 
								return InterrupterMessage{}, errors.New("Not a properly formatted accepted message")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fmt.Println(amsg.Accepter, "accepted your invite.", "Press Enter to connect to game...")
 | 
							fmt.Println(amsg.Accepter, "accepted your invite.", "Press Enter to connect to game...")
 | 
				
			||||||
@ -159,54 +154,60 @@ func HandleServerMessage(message lobby.LobbyMessage) (InterrupterMessage, error)
 | 
				
			|||||||
			InterruptType: "start_game",
 | 
								InterruptType: "start_game",
 | 
				
			||||||
			Content:       amsg.GameID,
 | 
								Content:       amsg.GameID,
 | 
				
			||||||
		}, nil
 | 
							}, nil
 | 
				
			||||||
	case "start_game":
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sgmsg, ok := msg.(lobby.StartGame)
 | 
						case lobby.StartGame:
 | 
				
			||||||
		if !ok {
 | 
							sgmsg, err := lobby.Unmarshal[lobby.StartGameData](msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
			return InterrupterMessage{}, errors.New("Not a properly formatted start game message")
 | 
								return InterrupterMessage{}, errors.New("Not a properly formatted start game message")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return InterrupterMessage{
 | 
							return InterrupterMessage{
 | 
				
			||||||
			InterruptType: "start_game",
 | 
								InterruptType: "start_game",
 | 
				
			||||||
			Content:       sgmsg.GameID,
 | 
								Content:       sgmsg.GameID,
 | 
				
			||||||
		}, nil
 | 
							}, nil
 | 
				
			||||||
	case "chat":
 | 
					
 | 
				
			||||||
		cmsg, ok := msg.(lobby.Chat)
 | 
						case lobby.Chat:
 | 
				
			||||||
		if !ok {
 | 
							cmsg, err := lobby.Unmarshal[lobby.ChatData](msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
			return InterrupterMessage{}, errors.New("Not a properly formatted chat message")
 | 
								return InterrupterMessage{}, errors.New("Not a properly formatted chat message")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fmt.Println(cmsg.From, ":", cmsg.Message)
 | 
							fmt.Println(cmsg.From, ":", cmsg.Message)
 | 
				
			||||||
	case "decline":
 | 
					
 | 
				
			||||||
		dmsg, ok := msg.(lobby.Decline)
 | 
						case lobby.Decline:
 | 
				
			||||||
		if !ok {
 | 
							dmsg, err := lobby.Unmarshal[lobby.DeclineData](msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
			return InterrupterMessage{}, errors.New("Not a properly formatted decline message")
 | 
								return InterrupterMessage{}, errors.New("Not a properly formatted decline message")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fmt.Println(dmsg.From, "declined your game invite")
 | 
							fmt.Println(dmsg.From, "declined your game invite")
 | 
				
			||||||
	case "disconnect":
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dmsg, ok := msg.(lobby.Disconnect)
 | 
						case lobby.Disconnect:
 | 
				
			||||||
		if !ok {
 | 
							dmsg, err := lobby.Unmarshal[lobby.DisconnectData](msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
			return InterrupterMessage{}, errors.New("Not a properly formatted disconnect message")
 | 
								return InterrupterMessage{}, errors.New("Not a properly formatted disconnect message")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		fmt.Println(dmsg.From, "has disconnected")
 | 
							fmt.Println(dmsg.From, "has disconnected")
 | 
				
			||||||
	case "connect":
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		cmsg, ok := msg.(lobby.Connect)
 | 
						case lobby.Connect:
 | 
				
			||||||
		if !ok {
 | 
							cmsg, err := lobby.Unmarshal[lobby.ConnectData](msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
			return InterrupterMessage{}, errors.New("Not a properly formated connect message")
 | 
								return InterrupterMessage{}, errors.New("Not a properly formated connect message")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fmt.Println(cmsg.From, "has connected")
 | 
							fmt.Println(cmsg.From, "has connected")
 | 
				
			||||||
	case "pong":
 | 
					
 | 
				
			||||||
		fmt.Println("Received pong")
 | 
						case lobby.CurrentlyConnected:
 | 
				
			||||||
	case "error":
 | 
							ccmsg, err := lobby.Unmarshal[lobby.CurrentlyConnectedData](msg)
 | 
				
			||||||
		em, ok := msg.(lobby.Error)
 | 
							if err != nil {
 | 
				
			||||||
		if !ok {
 | 
								return InterrupterMessage{}, errors.New("Not a properly formated connect message")
 | 
				
			||||||
			slog.Debug("Received an indecipherable error message...", slog.Any("msg", msg))
 | 
							}
 | 
				
			||||||
 | 
							fmt.Printf("Current Players\n%s\n", ccmsg.Players)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case lobby.Error:
 | 
				
			||||||
 | 
							em, err := lobby.Unmarshal[lobby.ErrorData](msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								slog.Debug("Received an indecipherable error message...", slog.Any("msg", msg[1:]))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fmt.Println(red, em.Message, normal)
 | 
							fmt.Println(red, em.Message, normal)
 | 
				
			||||||
	default:
 | 
					
 | 
				
			||||||
		fmt.Println("Received", message.MessageType, message.Message)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return InterrupterMessage{}, nil
 | 
						return InterrupterMessage{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,6 @@ package lobby
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"log/slog"
 | 
						"log/slog"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
@ -24,7 +23,7 @@ type Client struct {
 | 
				
			|||||||
type ExternalMessage struct {
 | 
					type ExternalMessage struct {
 | 
				
			||||||
	From    string
 | 
						From    string
 | 
				
			||||||
	Target  string
 | 
						Target  string
 | 
				
			||||||
	Message LobbyMessage
 | 
						Message []byte
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func CreateLobby() *Lobby {
 | 
					func CreateLobby() *Lobby {
 | 
				
			||||||
@ -52,13 +51,7 @@ func CreateLobby() *Lobby {
 | 
				
			|||||||
					slog.Debug("Item that was not a client found in the lobby map...", slog.Any("key", msg.From))
 | 
										slog.Debug("Item that was not a client found in the lobby map...", slog.Any("key", msg.From))
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				go func() {
 | 
									go func() {
 | 
				
			||||||
					em := LobbyMessage{
 | 
										b, err := Marshal(ErrorData{Message: fmt.Sprintf("Sorry player %s is not available...", msg.Target)}, Error)
 | 
				
			||||||
						MessageType: "error",
 | 
					 | 
				
			||||||
						Message: Error{
 | 
					 | 
				
			||||||
							Message: fmt.Sprintf("Sorry, player %s is not available...", msg.Target),
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					b, err := Marshal(em)
 | 
					 | 
				
			||||||
					if err != nil {
 | 
										if err != nil {
 | 
				
			||||||
						slog.Debug("Could not marshall error message for missing player", slog.Any("error", err))
 | 
											slog.Debug("Could not marshall error message for missing player", slog.Any("error", err))
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@ -68,16 +61,12 @@ func CreateLobby() *Lobby {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			c, ok := tc.(Client)
 | 
								c, ok := tc.(Client)
 | 
				
			||||||
			if !ok {
 | 
								if !ok {
 | 
				
			||||||
 | 
					 | 
				
			||||||
				slog.Debug("Item that was not a client found in the lobby map...", slog.Any("key", msg.From))
 | 
									slog.Debug("Item that was not a client found in the lobby map...", slog.Any("key", msg.From))
 | 
				
			||||||
 | 
									lm.Delete(msg.Target)
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			go func() {
 | 
								go func() {
 | 
				
			||||||
				b, err := Marshal(msg.Message)
 | 
									c.Conn.Write(msg.Message)
 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					slog.Debug("Could not marshal external message...", slog.Any("error", err))
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				c.Conn.Write(b)
 | 
					 | 
				
			||||||
			}()
 | 
								}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -86,33 +75,33 @@ func CreateLobby() *Lobby {
 | 
				
			|||||||
	return &l
 | 
						return &l
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *Lobby) HandleLobbyConnection(conn net.Conn) {
 | 
					func (l *Lobby) HandleLobbyConnection(client Client) {
 | 
				
			||||||
	messageBytes := make([]byte, 4096)
 | 
						messageBytes := make([]byte, 4096)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ingress := make(chan LobbyMessage)
 | 
						ingress := make(chan []byte)
 | 
				
			||||||
	egress := make(chan LobbyMessage)
 | 
						egress := make(chan []byte)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Network Reader
 | 
						// Network Reader
 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			n, err := conn.Read(messageBytes)
 | 
								n, err := client.Conn.Read(messageBytes)
 | 
				
			||||||
			if err == io.EOF {
 | 
					 | 
				
			||||||
				conn.Close()
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				conn.Close()
 | 
									client.Conn.Close()
 | 
				
			||||||
				log.Printf("Error reading message %v", err)
 | 
									log.Printf("Error reading message %v", err)
 | 
				
			||||||
 | 
									l.lobbyMembers.Delete(client.Username)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Server receives a disconnect message of the user
 | 
				
			||||||
 | 
									msg, err := Marshal(DisconnectData{
 | 
				
			||||||
 | 
										From: client.Username,
 | 
				
			||||||
 | 
									}, Disconnect)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										slog.Error("error marshalling responsive disconnect of EOF error", "error", err)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										ingress <- msg
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								ingress <- messageBytes[:n]
 | 
				
			||||||
			message := LobbyMessage{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			message, err = Unmarshal(messageBytes[:n])
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				log.Println("Invalid message received from client", err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			ingress <- message
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -120,21 +109,21 @@ func (l *Lobby) HandleLobbyConnection(conn net.Conn) {
 | 
				
			|||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			msg := <-egress
 | 
								msg := <-egress
 | 
				
			||||||
			bytes, err := Marshal(msg)
 | 
								_, err := client.Conn.Write(msg)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				log.Println("Error marshalling message to send to user...", err)
 | 
									client.Conn.Close()
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			_, err = conn.Write(bytes)
 | 
					 | 
				
			||||||
			if err == io.EOF {
 | 
					 | 
				
			||||||
				conn.Close()
 | 
					 | 
				
			||||||
				log.Println("User has disconnected", err)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// TODO: write message for disconnect to everyone?
 | 
									l.lobbyMembers.Delete(client.Username)
 | 
				
			||||||
				slog.Debug("Sending bad disconnect message")
 | 
					
 | 
				
			||||||
				ingress <- LobbyMessage{MessageType: "disconnect", Message: Disconnect{}}
 | 
									// Server receives a disconnect message of the user
 | 
				
			||||||
			}
 | 
									msg, err := Marshal(DisconnectData{
 | 
				
			||||||
 | 
										From: client.Username,
 | 
				
			||||||
 | 
									}, Disconnect)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
				log.Println("Error writing to user...", err)
 | 
										slog.Error("error marshalling responsive disconnect of EOF error", "error", err)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										ingress <- msg
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
@ -143,139 +132,158 @@ func (l *Lobby) HandleLobbyConnection(conn net.Conn) {
 | 
				
			|||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			msg := <-ingress
 | 
								msg := <-ingress
 | 
				
			||||||
			serverMsg, err := l.handleClientLobbyMessage(&msg, conn)
 | 
								slog.Debug("Received an ingress message", "message", msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								resMsg, err := l.handleClientLobbyMessage(msg)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				log.Println("Error handling client lobby message...", err)
 | 
									resMsg, err = Marshal(ErrorData{
 | 
				
			||||||
 | 
										Message: err.Error(),
 | 
				
			||||||
 | 
									}, Error)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if serverMsg.MessageType != "" {
 | 
								if len(resMsg) > 0 {
 | 
				
			||||||
				egress <- serverMsg
 | 
									egress <- resMsg
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Returns a bool of whether the player has disconnected from the lobby and an error
 | 
					func (l *Lobby) handleClientLobbyMessage(msg []byte) ([]byte, error) {
 | 
				
			||||||
func (l *Lobby) handleClientLobbyMessage(message *LobbyMessage, conn net.Conn) (LobbyMessage, error) {
 | 
						header := msg[0]
 | 
				
			||||||
	switch message.MessageType {
 | 
					
 | 
				
			||||||
	// Handle an name/login message from a player
 | 
						switch header {
 | 
				
			||||||
	// Store the new player in the l.lobbyMembers
 | 
						case Chat:
 | 
				
			||||||
	// Send a connection message for each of the l.lobbyMembers to the new player
 | 
							l.BroadcastToLobby(msg)
 | 
				
			||||||
	// Send a connection message to all members in the lobby
 | 
							return []byte{}, nil
 | 
				
			||||||
	case "name":
 | 
						case Invite:
 | 
				
			||||||
		_, ok := l.lobbyMembers.Load(message.Message)
 | 
							i, err := Unmarshal[InviteData](msg)
 | 
				
			||||||
		if ok {
 | 
							if err != nil {
 | 
				
			||||||
			return LobbyMessage{MessageType: "error", Message: Error{Message: "Sorry, that name is already taken, please try a different name"}}, nil
 | 
								slog.Debug("error unmarshalling invite message", "error", err)
 | 
				
			||||||
 | 
								return []byte{}, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		nm, ok := message.Message.(Name)
 | 
							msg, err := Marshal(InviteData{
 | 
				
			||||||
		if !ok {
 | 
								From: i.From,
 | 
				
			||||||
			return LobbyMessage{MessageType: "error", Message: Error{Message: "Sorry the message value and type were not matching for name"}}, nil
 | 
								To:   i.To,
 | 
				
			||||||
 | 
							}, Invite)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								slog.Error("error marshalling invite data...", "error", err)
 | 
				
			||||||
 | 
								return []byte{}, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		l.lobbyMembers.Store(nm.Name, Client{Username: nm.Name, Conn: conn})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Build current lobby list
 | 
					 | 
				
			||||||
		var lobby []string
 | 
					 | 
				
			||||||
		l.lobbyMembers.Range(func(lobbyUsername any, client any) bool {
 | 
					 | 
				
			||||||
			usernameString, _ := lobbyUsername.(string)
 | 
					 | 
				
			||||||
			lobby = append(lobby, usernameString)
 | 
					 | 
				
			||||||
			return true
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		l.broadcastToLobby(LobbyMessage{MessageType: "connect", Message: Name{Name: nm.Name}})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return LobbyMessage{MessageType: "name", Message: Name{
 | 
					 | 
				
			||||||
			Name: nm.Name,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		}, 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":
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		i, ok := message.Message.(Invite)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return LobbyMessage{MessageType: "error", Message: Error{Message: "Sorry the message value and type were not matching for invite"}}, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// TODO: figure out this shit
 | 
					 | 
				
			||||||
		l.ExternalMessageChannel <- ExternalMessage{
 | 
							l.ExternalMessageChannel <- ExternalMessage{
 | 
				
			||||||
			From:    i.From,
 | 
								From:    i.From,
 | 
				
			||||||
			Target:  i.To,
 | 
								Target:  i.To,
 | 
				
			||||||
			Message: LobbyMessage{},
 | 
								Message: msg,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return LobbyMessage{MessageType: "pending_invite", Message: PendingInvite{
 | 
							return Marshal(PendingInviteData{
 | 
				
			||||||
			Recipient: i.To,
 | 
								Recipient: i.To,
 | 
				
			||||||
		}}, nil
 | 
							}, PendingInvite)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Handle a accept message from a player that was invited
 | 
						// TODO: is pending invite really something that we need?
 | 
				
			||||||
	// Send a game_start message back to the player: message.Content
 | 
						// case PendingInvite:
 | 
				
			||||||
	// Send an accepted message back to the inviter: message.PlayerId
 | 
						// 	pi, err := Unmarshal[PendingInviteData](msg)
 | 
				
			||||||
	case "accept":
 | 
						// 	if err != nil {
 | 
				
			||||||
		gameID := uuid.NewString()
 | 
						// 		slog.Debug("error unmarshalling pending invite message", err)
 | 
				
			||||||
 | 
						// 		return
 | 
				
			||||||
 | 
						// 	}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		am, ok := message.Message.(Accept)
 | 
						case Accept:
 | 
				
			||||||
		if !ok {
 | 
							a, err := Unmarshal[AcceptData](msg)
 | 
				
			||||||
			return LobbyMessage{MessageType: "error", Message: Error{Message: "Sorry the message value and type were not matching for accept"}}, nil
 | 
							if err != nil {
 | 
				
			||||||
 | 
								slog.Debug("error unmarshalling accept message", "error", err)
 | 
				
			||||||
 | 
								return []byte{}, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		slog.Debug("incoming accept message", slog.Any("From", am.From), slog.Any("To", am.To))
 | 
							gID := uuid.NewString()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							msg, err := Marshal(AcceptedData{
 | 
				
			||||||
 | 
								Accepter: a.From,
 | 
				
			||||||
 | 
								GameID:   gID,
 | 
				
			||||||
 | 
							}, Accepted)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		l.ExternalMessageChannel <- ExternalMessage{
 | 
							l.ExternalMessageChannel <- ExternalMessage{
 | 
				
			||||||
			Target: am.To,
 | 
								From:    a.From,
 | 
				
			||||||
			Message: LobbyMessage{MessageType: "accepted", Message: Accepted{
 | 
								Target:  a.To,
 | 
				
			||||||
				Accepter: am.From,
 | 
								Message: msg,
 | 
				
			||||||
				GameID:   gameID,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return LobbyMessage{MessageType: "start_game", Message: StartGame{To: am.From, GameID: gameID}}, nil
 | 
					 | 
				
			||||||
	// Handle a chat message from a player with PlayerId
 | 
					 | 
				
			||||||
	case "chat":
 | 
					 | 
				
			||||||
		c, ok := message.Message.(Chat)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return LobbyMessage{MessageType: "error", Message: Error{Message: "Sorry the message value and type were not matching for chat"}}, nil
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		l.broadcastToLobby(LobbyMessage{MessageType: "text", Message: Chat{
 | 
					 | 
				
			||||||
			From:    c.From,
 | 
					 | 
				
			||||||
			Message: c.Message,
 | 
					 | 
				
			||||||
		}})
 | 
					 | 
				
			||||||
		return LobbyMessage{}, nil
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Handle a quit message from a player that was connected
 | 
							return Marshal(StartGameData{
 | 
				
			||||||
	// broadcast the player quit to the lobby
 | 
								To:     a.From,
 | 
				
			||||||
	case "quit":
 | 
								GameID: gID,
 | 
				
			||||||
		q, ok := message.Message.(Disconnect)
 | 
							}, StartGame)
 | 
				
			||||||
		if !ok {
 | 
					
 | 
				
			||||||
			return LobbyMessage{MessageType: "error", Message: Error{Message: "Sorry the message value and type were not matching for quit"}}, nil
 | 
						case Accepted:
 | 
				
			||||||
 | 
							a, err := Unmarshal[AcceptedData](msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								slog.Debug("error unmarshalling accpeted message", "error", err)
 | 
				
			||||||
 | 
								return []byte{}, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		l.lobbyMembers.Delete(q.From)
 | 
					 | 
				
			||||||
		l.broadcastToLobby(LobbyMessage{MessageType: "disconnect", Message: Disconnect{
 | 
					 | 
				
			||||||
			From: q.From,
 | 
					 | 
				
			||||||
		}})
 | 
					 | 
				
			||||||
		return LobbyMessage{}, nil
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ping and pong
 | 
							// TODO: figure out the accepted and start game data situation... To field is a little hard to fill.
 | 
				
			||||||
	case "ping":
 | 
							return Marshal(StartGameData{
 | 
				
			||||||
		return LobbyMessage{MessageType: "pong", Message: "pong"}, nil
 | 
								To:     "",
 | 
				
			||||||
 | 
								GameID: a.GameID,
 | 
				
			||||||
 | 
							}, StartGame)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ping and pong
 | 
						// TODO: Like pending invite, I think start game is only a client message
 | 
				
			||||||
	default:
 | 
						// case StartGame:
 | 
				
			||||||
		return LobbyMessage{MessageType: "pong", Message: "pong"}, nil
 | 
						// 	sg, err := Unmarshal[StartGameData](msg)
 | 
				
			||||||
 | 
						// 	if err != nil {
 | 
				
			||||||
 | 
						// 		slog.Debug("error unmarshalling start game message", err)
 | 
				
			||||||
 | 
						// 		return []byte{}, err
 | 
				
			||||||
 | 
						// 	}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: Do we even want to support decline responses?
 | 
				
			||||||
 | 
						// case Decline:
 | 
				
			||||||
 | 
						// 	d, err := Unmarshal[DeclineData](msg)
 | 
				
			||||||
 | 
						// 	if err != nil {
 | 
				
			||||||
 | 
						// 		slog.Debug("error unmarshalling decline message", err)
 | 
				
			||||||
 | 
						// 		return []byte{}, err
 | 
				
			||||||
 | 
						// 	}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case Disconnect:
 | 
				
			||||||
 | 
							d, err := Unmarshal[DisconnectData](msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								slog.Debug("error unmarshalling disconnect message", "error", err)
 | 
				
			||||||
 | 
								return []byte{}, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							l.lobbyMembers.Delete(d.From)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							msg, err := Marshal(DisconnectData{
 | 
				
			||||||
 | 
								From: d.From,
 | 
				
			||||||
 | 
							}, Disconnect)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							l.BroadcastToLobby(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// TODO: how do we handle a disconnect for the client's side
 | 
				
			||||||
 | 
							return []byte{}, nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// TODO: This is just a client side message right...?
 | 
				
			||||||
 | 
							// case Connect:
 | 
				
			||||||
 | 
							// 	c, err := Unmarshal[ConnectData](msg)
 | 
				
			||||||
 | 
							// 	if err != nil {
 | 
				
			||||||
 | 
							// 		slog.Debug("error unmarshalling connect message", err)
 | 
				
			||||||
 | 
							// 		return
 | 
				
			||||||
 | 
							// 	}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// TODO: This is just a client side message right...?
 | 
				
			||||||
 | 
							// case Error:
 | 
				
			||||||
 | 
							// 	e, err := Unmarshal[ErrorData](msg)
 | 
				
			||||||
 | 
							// 	if err != nil {
 | 
				
			||||||
 | 
							// 		slog.Debug("error unmarshalling error message", err)
 | 
				
			||||||
 | 
							// 		return []byte{}, err
 | 
				
			||||||
 | 
							// 	}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return []byte{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *Lobby) broadcastToLobby(message LobbyMessage) {
 | 
					func (l *Lobby) BroadcastToLobby(bytes []byte) {
 | 
				
			||||||
	var disconnectedUsers []string
 | 
						var disconnectedUsers []string
 | 
				
			||||||
	l.lobbyMembers.Range(func(playerId, player interface{}) bool {
 | 
						l.lobbyMembers.Range(func(playerId, player interface{}) bool {
 | 
				
			||||||
		bytes, err := Marshal(message)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			log.Println("Error marshalling broadcast message", err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		client := player.(Client)
 | 
							client := player.(Client)
 | 
				
			||||||
		_, err = client.Conn.Write(bytes)
 | 
							_, err := client.Conn.Write(bytes)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.Println("Error broadcasting to clients...", err)
 | 
								log.Println("Error broadcasting to clients...", err)
 | 
				
			||||||
			disconnectedUsers = append(disconnectedUsers, playerId.(string))
 | 
								disconnectedUsers = append(disconnectedUsers, playerId.(string))
 | 
				
			||||||
@ -288,3 +296,62 @@ func (l *Lobby) broadcastToLobby(message LobbyMessage) {
 | 
				
			|||||||
		l.lobbyMembers.Delete(player)
 | 
							l.lobbyMembers.Delete(player)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					func (l *Lobby) InitialConnectionHandler(conn net.Conn) (Client, []byte) {
 | 
				
			||||||
 | 
						msg := make([]byte, 256)
 | 
				
			||||||
 | 
						nb, err := conn.Read(msg)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							slog.Debug("error reading from initial connection")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						msg = msg[:nb]
 | 
				
			||||||
 | 
						n, err := Unmarshal[NameData](msg)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							slog.Debug("error unmarshalling name message:", "error", err.Error(), "message", msg[1:nb])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							msgOut, err := Marshal(ErrorData{
 | 
				
			||||||
 | 
								Message: "incorrectly formatted username in name message",
 | 
				
			||||||
 | 
							}, Error)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								slog.Error("error marshalling error message for incorrectly formatted username")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return Client{}, msgOut
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, ok := l.lobbyMembers.Load(n.Name)
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							msg, err := Marshal(ErrorData{
 | 
				
			||||||
 | 
								Message: "Sorry that name is already taken, please try a different name",
 | 
				
			||||||
 | 
							}, Error)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								slog.Error("error marshalling error on name already taken msg")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return Client{}, msg
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						h, err := Marshal(ConnectData{
 | 
				
			||||||
 | 
							From: n.Name,
 | 
				
			||||||
 | 
						}, Connect)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							slog.Debug("error marshalling broadcast connect message on player connect", "error", err)
 | 
				
			||||||
 | 
							return Client{Username: n.Name, Conn: conn}, h
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						l.BroadcastToLobby(h)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Build current lobby list
 | 
				
			||||||
 | 
						var lobby []string
 | 
				
			||||||
 | 
						l.lobbyMembers.Range(func(lobbyUsername any, client any) bool {
 | 
				
			||||||
 | 
							usernameString, _ := lobbyUsername.(string)
 | 
				
			||||||
 | 
							lobby = append(lobby, usernameString)
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						msgOut, err := Marshal(CurrentlyConnectedData{Players: lobby}, CurrentlyConnected)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							slog.Debug("Error marshalling currectly connected data on player connect")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client := Client{
 | 
				
			||||||
 | 
							Username: n.Name,
 | 
				
			||||||
 | 
							Conn:     conn,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						l.lobbyMembers.Store(n.Name, client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return client, msgOut
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,244 +1,94 @@
 | 
				
			|||||||
package lobby
 | 
					package lobby
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import "encoding/json"
 | 
				
			||||||
	"encoding/base64"
 | 
					
 | 
				
			||||||
	"encoding/json"
 | 
					const (
 | 
				
			||||||
	"errors"
 | 
						Name = iota
 | 
				
			||||||
	"log/slog"
 | 
						Chat
 | 
				
			||||||
	"reflect"
 | 
						Invite
 | 
				
			||||||
	"strings"
 | 
						PendingInvite
 | 
				
			||||||
 | 
						Accept
 | 
				
			||||||
 | 
						Accepted
 | 
				
			||||||
 | 
						StartGame
 | 
				
			||||||
 | 
						Decline
 | 
				
			||||||
 | 
						Disconnect
 | 
				
			||||||
 | 
						Connect
 | 
				
			||||||
 | 
						CurrentlyConnected
 | 
				
			||||||
 | 
						Error
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type LobbyMessage struct {
 | 
					type NameData struct {
 | 
				
			||||||
	MessageType string `json:"message_type"`
 | 
					 | 
				
			||||||
	Message     any    `json:"message"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Name struct {
 | 
					 | 
				
			||||||
	Name string `json:"name"`
 | 
						Name string `json:"name"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Chat struct {
 | 
					type ChatData struct {
 | 
				
			||||||
	From    string `json:"from"`
 | 
						From    string `json:"from"`
 | 
				
			||||||
	Message string `json:"message"`
 | 
						Message string `json:"message"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Invite struct {
 | 
					type InviteData struct {
 | 
				
			||||||
	From string `json:"from"`
 | 
						From string `json:"from"`
 | 
				
			||||||
	To   string `json:"to"`
 | 
						To   string `json:"to"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type PendingInvite struct {
 | 
					type PendingInviteData struct {
 | 
				
			||||||
	Recipient string `json:"recipient"`
 | 
						Recipient string `json:"recipient"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Accept struct {
 | 
					type AcceptData struct {
 | 
				
			||||||
	From string `json:"from"`
 | 
						From string `json:"from"`
 | 
				
			||||||
	To   string `json:"to"`
 | 
						To   string `json:"to"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Accepted struct {
 | 
					type AcceptedData struct {
 | 
				
			||||||
	Accepter string `json:"accepter"`
 | 
						Accepter string `json:"accepter"`
 | 
				
			||||||
	GameID   string `json:"game_id"`
 | 
						GameID   string `json:"game_id"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type StartGame struct {
 | 
					type StartGameData struct {
 | 
				
			||||||
	To     string `json:"to"`
 | 
						To     string `json:"to"`
 | 
				
			||||||
	GameID string `json:"game_id"`
 | 
						GameID string `json:"game_id"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Decline struct {
 | 
					type DeclineData struct {
 | 
				
			||||||
	From string `json:"from"`
 | 
						From string `json:"from"`
 | 
				
			||||||
	To   string `json:"to"`
 | 
						To   string `json:"to"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Disconnect struct {
 | 
					type DisconnectData struct {
 | 
				
			||||||
	From string `json:"from"`
 | 
						From string `json:"from"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Connect struct {
 | 
					type ConnectData struct {
 | 
				
			||||||
	From string `json:"from"`
 | 
						From string `json:"from"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Error struct {
 | 
					type CurrentlyConnectedData struct {
 | 
				
			||||||
 | 
						Players []string `json:"players"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ErrorData struct {
 | 
				
			||||||
	Message string `json:"message"`
 | 
						Message string `json:"message"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Marshal(a LobbyMessage) ([]byte, error) {
 | 
					func Unmarshal[T NameData | ChatData | InviteData | PendingInviteData | AcceptData | AcceptedData | StartGameData | DeclineData | DisconnectData | ConnectData | CurrentlyConnectedData | ErrorData](msg []byte) (T, error) {
 | 
				
			||||||
	slog.Debug("Marshalling message", slog.Any("message type", a.MessageType))
 | 
						var d T
 | 
				
			||||||
	bm, err := json.Marshal(a.Message)
 | 
						err := json.Unmarshal(msg[1:], &d)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return d, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return d, nil
 | 
				
			||||||
	a.Message = bm
 | 
					 | 
				
			||||||
	return json.Marshal(a)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Use this to get the appropriate message type into the message field then assert the
 | 
					func Marshal[T NameData | ChatData | InviteData | PendingInviteData | AcceptData | AcceptedData | StartGameData | DeclineData | DisconnectData | ConnectData | CurrentlyConnectedData | ErrorData](msg T, header int) ([]byte, error) {
 | 
				
			||||||
// right struct accordingly to safely access the fields you need.
 | 
						mb, err := json.Marshal(msg)
 | 
				
			||||||
func Unmarshal(b []byte) (LobbyMessage, error) {
 | 
					 | 
				
			||||||
	lm := LobbyMessage{}
 | 
					 | 
				
			||||||
	err := json.Unmarshal(b, &lm)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return lm, err
 | 
							return mb, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	smsg, ok := lm.Message.(string)
 | 
						b := []byte{byte(header)}
 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		slog.Debug("error asserting message to string")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	slog.Debug("type of message", slog.Any("type of message", reflect.TypeOf(smsg)), slog.String("message", smsg))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	jsonBytes, err := base64.StdEncoding.DecodeString(smsg)
 | 
						b = append(b, mb...)
 | 
				
			||||||
	lm.Message = jsonBytes
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch strings.ToLower(lm.MessageType) {
 | 
						return b, nil
 | 
				
			||||||
	case "name":
 | 
					 | 
				
			||||||
		n := Name{}
 | 
					 | 
				
			||||||
		bs, ok := lm.Message.([]byte)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		err := json.Unmarshal(bs, &n)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Debug("Error", slog.Any("error", err))
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lm.Message = n
 | 
					 | 
				
			||||||
		return lm, nil
 | 
					 | 
				
			||||||
	case "chat":
 | 
					 | 
				
			||||||
		c := Chat{}
 | 
					 | 
				
			||||||
		bs, ok := lm.Message.([]byte)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err := json.Unmarshal(bs, &c)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Debug("chat", slog.Any("error", err))
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lm.Message = c
 | 
					 | 
				
			||||||
		return lm, nil
 | 
					 | 
				
			||||||
	case "invite":
 | 
					 | 
				
			||||||
		i := Invite{}
 | 
					 | 
				
			||||||
		bs, ok := lm.Message.([]byte)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err := json.Unmarshal(bs, &i)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Debug("invite", slog.Any("error", err))
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lm.Message = i
 | 
					 | 
				
			||||||
		return lm, nil
 | 
					 | 
				
			||||||
	case "pending_invite":
 | 
					 | 
				
			||||||
		pi := PendingInvite{}
 | 
					 | 
				
			||||||
		bs, ok := lm.Message.([]byte)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err := json.Unmarshal(bs, &pi)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Debug("pending_invite", slog.Any("error", err))
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lm.Message = pi
 | 
					 | 
				
			||||||
	case "accept":
 | 
					 | 
				
			||||||
		a := Accept{}
 | 
					 | 
				
			||||||
		bs, ok := lm.Message.([]byte)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err := json.Unmarshal(bs, &a)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Debug("accept", slog.Any("error", err))
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lm.Message = a
 | 
					 | 
				
			||||||
		return lm, nil
 | 
					 | 
				
			||||||
	case "accepted":
 | 
					 | 
				
			||||||
		a := Accepted{}
 | 
					 | 
				
			||||||
		bs, ok := lm.Message.([]byte)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err := json.Unmarshal(bs, &a)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Debug("accepted", slog.Any("error", err))
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lm.Message = a
 | 
					 | 
				
			||||||
		return lm, nil
 | 
					 | 
				
			||||||
	case "start_game":
 | 
					 | 
				
			||||||
		sg := StartGame{}
 | 
					 | 
				
			||||||
		bs, ok := lm.Message.([]byte)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err := json.Unmarshal(bs, &sg)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Debug("start_game", slog.Any("error", err))
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lm.Message = sg
 | 
					 | 
				
			||||||
		return lm, nil
 | 
					 | 
				
			||||||
	case "decline":
 | 
					 | 
				
			||||||
		d := Decline{}
 | 
					 | 
				
			||||||
		bs, ok := lm.Message.([]byte)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err := json.Unmarshal(bs, &d)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Debug("decline", slog.Any("error", err))
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lm.Message = d
 | 
					 | 
				
			||||||
		return lm, nil
 | 
					 | 
				
			||||||
	case "disconnect":
 | 
					 | 
				
			||||||
		di := Disconnect{}
 | 
					 | 
				
			||||||
		bs, ok := lm.Message.([]byte)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err := json.Unmarshal(bs, &di)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Debug("disconnect", slog.Any("error", err))
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lm.Message = di
 | 
					 | 
				
			||||||
		return lm, nil
 | 
					 | 
				
			||||||
	case "connect":
 | 
					 | 
				
			||||||
		co := Connect{}
 | 
					 | 
				
			||||||
		bs, ok := lm.Message.([]byte)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err := json.Unmarshal(bs, &co)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Debug("connect", slog.Any("error", err))
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lm.Message = co
 | 
					 | 
				
			||||||
		return lm, nil
 | 
					 | 
				
			||||||
	case "error":
 | 
					 | 
				
			||||||
		e := Error{}
 | 
					 | 
				
			||||||
		bs, ok := lm.Message.([]byte)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err := json.Unmarshal(bs, &e)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Debug("error", slog.Any("error", err))
 | 
					 | 
				
			||||||
			return lm, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lm.Message = e
 | 
					 | 
				
			||||||
		return lm, nil
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return lm, errors.New("unknown message type")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return lm, errors.New("unknown message type")
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user