package main import ( "encoding/binary" "errors" "hash/crc32" "net" "strconv" "strings" ) // sendPacket sends a packet with the given packetID and data over the provided TCP connection. func sendPacket(packetID uint8, data []byte, conn *net.TCPConn) error { // Create a buffer with the packet ID and data tempBuffer := append([]byte{packetID}, data...) // Calculate the checksum of the packet ID + data checksum := crc32.ChecksumIEEE(tempBuffer) // Convert the checksum to a 4-byte slice checksumBytes := make([]byte, 4) binary.LittleEndian.PutUint32(checksumBytes, checksum) // Prepend the checksum to the beginning of the buffer tempBuffer = append(checksumBytes, tempBuffer...) // Calculate the total length (checksum + packet ID + data) packetLength := uint32(len(tempBuffer)) // Prepare the output buffer with the length field outBuffer := make([]byte, 4) binary.LittleEndian.PutUint32(outBuffer, packetLength) // Append the tempBuffer (checksum + packet ID + data) to outBuffer outBuffer = append(outBuffer, tempBuffer...) // Send the packet over the connection writeLen, err := conn.Write(outBuffer) if err != nil { return err } if writeLen != len(outBuffer) { return errors.New("write length does not match output buffer length") } return nil } // receivePacket receives a packet from the provided TCP connection and verifies it. func receivePacket(conn *net.TCPConn) (uint8, uint32, []byte, error) { // Step 1: Read the packet length (4 bytes) lengthBuffer := make([]byte, 4) n, err := conn.Read(lengthBuffer) if err != nil { return 0, 0, nil, err } if n != len(lengthBuffer) { return 0, 0, nil, errors.New("read length does not match read length") } packetLength := binary.LittleEndian.Uint32(lengthBuffer) // Step 2: Allocate a buffer to hold the rest of the packet (checksum + packetID + data) packetBuffer := make([]byte, packetLength) n, err = conn.Read(packetBuffer) if err != nil { return 0, 0, nil, err } if n != int(packetLength) { return 0, 0, nil, errors.New("read length does not match packet length") } // Ensure we've read enough bytes if uint32(len(packetBuffer)) != packetLength { return 0, 0, nil, errors.New("incomplete packet received") } // Step 3: Extract the checksum (4 bytes) receivedChecksum := binary.LittleEndian.Uint32(packetBuffer[:4]) // Step 4: Extract the packet ID (1 byte) packetID := packetBuffer[4] // Step 5: Extract the data data := packetBuffer[5:] // Step 6: Verify the checksum calculatedChecksum := crc32.ChecksumIEEE(append([]byte{packetID}, data...)) if receivedChecksum != calculatedChecksum { return 0, 0, nil, errors.New("checksum mismatch") } // Return the packet ID and data return packetID, uint32(len(data)), data, nil } func boolToByte(b bool) byte { if b { return 1 } return 0 } func byteToBool(b byte) bool { return b == 1 } func getCurrentVersion() []uint8 { versionArrayString := strings.Split(GameVersion, ".") if len(versionArrayString) < 3 { return []uint8{} } var versionArray []uint8 for i := 0; i < len(versionArrayString); i++ { intVersion, _ := strconv.Atoi(versionArrayString[i]) versionArray = append(versionArray, uint8(intVersion)) } return versionArray }