package server import ( "encoding/binary" "fmt" "io" "log" "net" "strconv" ) const ( MsgKeyPress uint16 = 1 MsgGameState uint16 = 2 MSGServerStatus uint16 = 3 MSGOnConnect uint16 = 4 ) var num_clients int = 0 var clients = map[int]net.Conn{} func Start() { listener, err := net.Listen("tcp", ":9000") if err != nil { log.Fatal(err) } fmt.Println("Server listening on port 9000") for { conn, err := listener.Accept() if err != nil { fmt.Println("Accept error:", err) continue } num_clients += 1 client_id := strconv.Itoa(num_clients) fmt.Println(client_id) go SendPacket(MSGOnConnect, []byte(client_id)) addClient(conn, num_clients) go handle(conn) } } func addClient(conn net.Conn, id int) { clients[id] = conn } func SendPacket(msgID uint16, payload []byte) error { // Length matches Lua: 2 (msgID) + payload size length := uint32(2 + len(payload)) buf := make([]byte, 4+2+len(payload)) binary.BigEndian.PutUint32(buf[0:4], length) binary.BigEndian.PutUint16(buf[4:6], msgID) copy(buf[6:], payload) for _, conn := range clients { n, err := conn.Write(buf) if err != nil { return err } if n != len(buf) { return fmt.Errorf("short write: expected %d bytes, got %d", len(buf), n) } } return nil } func handle(conn net.Conn) { defer conn.Close() for { // Read packet length var length uint32 err := binary.Read(conn, binary.BigEndian, &length) if err != nil { if err != io.EOF { fmt.Println("Read length error:", err) } fmt.Println("Client disconnected") num_clients -= 1 return } // Prevent invalid packets if length < 2 { fmt.Println("Invalid packet length:", length) return } // Read message ID var msgID uint16 err = binary.Read(conn, binary.BigEndian, &msgID) if err != nil { fmt.Println("Read message ID error:", err) return } // Read payload payload := make([]byte, length-2) _, err = io.ReadFull(conn, payload) if err != nil { fmt.Println("Read payload error:", err) return } switch msgID { case MsgKeyPress: msg := string(payload) fmt.Println(msg) // Send something back to the client go SendPacket(MsgGameState, []byte(msg)) default: fmt.Println("Unknown message:", msgID) } } }