package main import ( "encoding/json" "errors" "fmt" "net" ) const ( HandshakePacketID = 0x00 StatusRequestID = 0x00 StatusResponseID = 0x00 ) const ( SEGMENT_BITS = 0x7F CONTINUE_BIT = 0x80 ) type HandshakePacket struct { ProtocolVersion int ServerAddress string ServerPort uint16 NextState int } type StatusResponse struct { Version VersionInfo `json:"version"` Players PlayerInfo `json:"players"` Description Chat `json:"description"` } type VersionInfo struct { Name string `json:"name"` Protocol int `json:"protocol"` } type PlayerInfo struct { Max int `json:"max"` Online int `json:"online"` Sample []Player `json:"sample"` } type Player struct { Name string `json:"name"` ID string `json:"id"` } type Chat struct { Text string `json:"text"` } type Reader struct { data []byte cursor int } type ClientState struct { conn net.Conn nextState int } func main() { listener, err := net.Listen("tcp", "localhost:25565") if err != nil { fmt.Println("Error starting server:", err) return } defer listener.Close() fmt.Println("Server started on port 25565") for { conn, err := listener.Accept() if err != nil { fmt.Println("Error accepting connection:", err) continue } client := &ClientState{conn: conn, nextState: 0} go handleConnection(client) } } func handleConnection(client *ClientState) { defer client.conn.Close() fmt.Println("New connection from:", client.conn.RemoteAddr()) r := &Reader{data: make([]byte, 0)} buf := make([]byte, 1024) for { n, err := client.conn.Read(buf) if err != nil { fmt.Println("Error reading from connection or connection closed:", err) break } // Append new data to the reader buffer r.data = append(r.data, buf[:n]...) // Process packets as long as there is data for len(r.data) > 0 { startCursor := r.cursor packetLength, err := r.readVarInt() if err != nil { r.cursor = startCursor // Reset if incomplete packet break } if len(r.data[r.cursor:]) < packetLength { r.cursor = startCursor // Reset if incomplete packet break } packetID, err := r.readVarInt() if err != nil { fmt.Println("Error reading packet ID:", err) break } fmt.Println("Packet ID:", packetID) if packetID == StatusRequestID && client.nextState == 1 { handleStatusRequest(client.conn) } else { if packetID == HandshakePacketID { handshake, err := handleHandshake(r) if err != nil { fmt.Println("Error processing handshake:", err) return } client.nextState = handshake.NextState } } // Remove processed data r.data = r.data[r.cursor:] r.cursor = 0 } } } func handleHandshake(r *Reader) (HandshakePacket, error) { var handshake HandshakePacket if err := readHandshakePacket(r, &handshake); err != nil { fmt.Println("Error reading handshake packet:", err) return handshake, err } return handshake, nil } func handleStatusRequest(conn net.Conn) { status := StatusResponse{ Version: VersionInfo{ Name: "1.17.1", Protocol: 756, }, Players: PlayerInfo{ Max: 100, Online: 5, Sample: []Player{}, }, Description: Chat{ Text: "A Minecraft Server", }, } response, err := json.Marshal(status) if err != nil { fmt.Println("Error marshaling status response:", err) return } w := &Writer{data: make([]byte, 1024)} if err := w.writeVarInt(StatusResponseID); err != nil { fmt.Println("Error writing response ID:", err) return } if err := w.writeVarInt(len(response)); err != nil { fmt.Println("Error writing response length:", err) return } if err := w.writeString(string(response)); err != nil { fmt.Println("Error writing response:", err) return } // Send response to client _, err = conn.Write(w.data[:w.cursor]) if err != nil { fmt.Println("Error sending response:", err) } } func (r *Reader) readByte() (byte, error) { if r.cursor >= len(r.data) { return 0, errors.New("EOF") } b := r.data[r.cursor] r.cursor++ return b, nil } func (r *Reader) readVarInt() (int, error) { value := 0 position := 0 for { currentByte, err := r.readByte() if err != nil { return 0, err } value |= int(currentByte&SEGMENT_BITS) << position if (currentByte & CONTINUE_BIT) == 0 { break } position += 7 if position >= 32 { return 0, errors.New("VarInt is too big") } } return value, nil } func (r *Reader) readString() (string, error) { length, err := r.readVarInt() if err != nil { return "", err } if r.cursor+length > len(r.data) { return "", errors.New("EOF: Reached String unexpectedly") } str := string(r.data[r.cursor : r.cursor+length]) r.cursor += length return str, nil } func (r *Reader) readUnsignedShort() (uint16, error) { b1, err := r.readByte() if err != nil { return 0, err } b2, err := r.readByte() if err != nil { return 0, err } return uint16(b1)<<8 | uint16(b2), nil } type Writer struct { data []byte cursor int } func (w *Writer) writeByte(b byte) error { if w.cursor >= len(w.data) { return errors.New("EOF") } w.data[w.cursor] = b w.cursor++ return nil } func (w *Writer) writeVarInt(value int) error { for { temp := byte(value & SEGMENT_BITS) value >>= 7 if value != 0 { temp |= CONTINUE_BIT } if err := w.writeByte(temp); err != nil { return err } if value == 0 { break } } return nil } func (w *Writer) writeString(s string) error { length := len(s) if err := w.writeVarInt(length); err != nil { return err } if w.cursor+length > len(w.data) { return errors.New("EOF") } copy(w.data[w.cursor:], s) w.cursor += length return nil } func writeByte(conn net.Conn, b byte) error { _, err := conn.Write([]byte{b}) return err } func writeVarInt(conn net.Conn, value int) error { var buf [5]byte n := 0 for { temp := byte(value & SEGMENT_BITS) value >>= 7 if value != 0 { temp |= CONTINUE_BIT } buf[n] = temp n++ if value == 0 { break } } _, err := conn.Write(buf[:n]) return err } func readHandshakePacket(r *Reader, packet *HandshakePacket) error { // Print the whole packet fmt.Println("Packet: ", r.data) fmt.Println("Works so far") var err error packet.ProtocolVersion, err = r.readVarInt() fmt.Println("version: ", packet.ProtocolVersion) if err != nil { return err } packet.ServerAddress, err = r.readString() fmt.Println(packet.ServerAddress) if err != nil { return err } port, err := r.readUnsignedShort() if err != nil { return err } packet.ServerPort = port fmt.Println("Port: ", packet.ServerPort) packet.NextState, err = r.readVarInt() fmt.Println("Next state: ", packet.NextState) if err != nil { return err } return nil }