package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"log"
	"net"
)

// MinecraftProtocolVersion — версия протокола для Minecraft 1.20.1 (763)
const MinecraftProtocolVersion = 763

// ServerAddress — адрес сервера
const ServerAddress = "localhost:25565"

// Username — имя бота
const Username = "BotPlayer"

// HandshakePacketID — ID пакета рукопожатия
const HandshakePacketID = 0x00

// LoginStartPacketID — ID пакета начала логина
const LoginStartPacketID = 0x00

// PacketWriter — вспомогательная структура для записи данных пакета
type PacketWriter struct {
	buffer bytes.Buffer
}

// WriteVarInt — запись VarInt в пакет
func (w *PacketWriter) WriteVarInt(value int32) {
	for {
		temp := byte(value & 0x7F)
		value >>= 7
		if value != 0 {
			temp |= 0x80
		}
		w.buffer.WriteByte(temp)
		if value == 0 {
			break
		}
	}
}

// WriteString — запись строки в пакет
func (w *PacketWriter) WriteString(value string) {
	w.WriteVarInt(int32(len(value)))
	w.buffer.WriteString(value)
}

// WriteByte — запись байта в пакет
func (w *PacketWriter) WriteByte(value byte) {
	w.buffer.WriteByte(value)
}

// WriteShort — запись короткого значения в пакет
func (w *PacketWriter) WriteShort(value int16) {
	binary.Write(&w.buffer, binary.BigEndian, value)
}

// Bytes — получение байтов пакета
func (w *PacketWriter) Bytes() []byte {
	return w.buffer.Bytes()
}

// SendPacket — отправка пакета на сервер
func SendPacket(conn net.Conn, packet []byte) error {
	packetLength := len(packet)
	writer := &PacketWriter{}
	writer.WriteVarInt(int32(packetLength))
	packetWithLength := append(writer.Bytes(), packet...)
	_, err := conn.Write(packetWithLength)
	return err
}

func main() {
	// Подключаемся к серверу по TCP
	conn, err := net.Dial("tcp", ServerAddress)
	if err != nil {
		log.Fatalf("Не удалось подключиться к серверу: %v", err)
	}
	defer conn.Close()

	fmt.Println("Успешно подключились к серверу!")

	// Отправляем пакет рукопожатия (Handshake)
	err = SendHandshakePacket(conn)
	if err != nil {
		log.Fatalf("Ошибка при отправке рукопожатия: %v", err)
	}
	fmt.Println("Рукопожатие отправлено успешно!")

	// Отправляем пакет начала логина (Login Start)
	err = SendLoginStartPacket(conn)
	if err != nil {
		log.Fatalf("Ошибка при отправке пакета начала логина: %v", err)
	}
	fmt.Println("Пакет начала логина отправлен успешно!")

	// Обрабатываем дальнейшие данные с сервера
	HandleServerResponse(conn)
}

func SendHandshakePacket(conn net.Conn) error {
	writer := &PacketWriter{}
	writer.WriteVarInt(HandshakePacketID)        // ID пакета рукопожатия (0x00)
	writer.WriteVarInt(MinecraftProtocolVersion) // Версия протокола (763 для 1.20.1)
	writer.WriteString("localhost")              // Адрес сервера
	writer.WriteShort(25565)                     // Порт сервера
	writer.WriteVarInt(2)                        // Режим подключения (2 = логин)

	// Отправляем Handshake пакет на сервер
	return SendPacket(conn, writer.Bytes())
}

func SendLoginStartPacket(conn net.Conn) error {
	writer := &PacketWriter{}
	writer.WriteVarInt(LoginStartPacketID) // ID пакета начала логина (0x00)
	writer.WriteString(Username)           // Имя пользователя

	// Отправляем пакет Login Start
	return SendPacket(conn, writer.Bytes())
}

func HandleServerResponse(conn net.Conn) {
	// Ожидаем ответ от сервера
	buf := make([]byte, 1024)
	n, err := conn.Read(buf)
	if err != nil {
		log.Fatalf("Ошибка при чтении данных с сервера: %v", err)
	}

	// Проверяем ответ
	fmt.Printf("Ответ от сервера (hex): %x\n", buf[:n])

	// Определение пакета Disconnect (первый байт 0x00)
	if buf[0] == 0x00 {
		fmt.Println("Сервер разорвал соединение.")
		// Декодируем текст сообщения
		var messageLength int32
		err = binary.Read(bytes.NewReader(buf[1:]), binary.BigEndian, &messageLength)
		if err != nil {
			log.Fatalf("Ошибка при декодировании сообщения о разрыве: %v", err)
		}
		fmt.Printf("Сообщение о разрыве: %s\n", string(buf[5:5+messageLength]))
		return
	}

	fmt.Println("Бот подключился успешно!")
}


Успешно подключились к серверу!
Рукопожатие отправлено успешно!
Пакет начала логина отправлен успешно!
Ответ от сервера (hex): c60200c3027b227472616e736c617465223a22646973636f6e6e6563742e67656e65726963526561736f6e222c2277697468223a5b22496e7465726e616c20457863657074696f6e3a20696f2e6e657474792e68616e646c65722e636f6465632e4465636f646572457863657074696f6e3a206a6176612e6c616e672e496e6465784f75744f66426f756e6473457863657074696f6e3a20726561646572496e64657828313129202b206c656e677468283129206578636565647320777269746572496e646578283131293a20506f6f6c6564536c696365644279746542756628726964783a2031312c20776964783a2031312c206361703a2031312f31312c20756e777261707065643a20506f6f6c6564556e736166654469726563744279746542756628726964783a2032392c20776964783a2032392c206361703a20323034382929225d7d
Бот подключился успешно!


бота нету на серверер исправь