144 lines
5.7 KiB
Rust
144 lines
5.7 KiB
Rust
use std::net::{TcpListener, TcpStream};
|
|
use std::io::{Read, Write};
|
|
use std::thread;
|
|
mod data_dumps;
|
|
|
|
fn handle_client(mut stream: TcpStream) {
|
|
let mut buffer = vec![0; 1024];
|
|
|
|
while let Ok(size) = stream.read(&mut buffer) {
|
|
if size == 0 {
|
|
println!("Client disconnected.");
|
|
break;
|
|
}
|
|
|
|
let packet_id = buffer[0];
|
|
println!("Received Packet ID: 0x{:02X}", packet_id);
|
|
|
|
// Print the hexadecimal representation of the entire packet
|
|
let packet_hex: Vec<String> = buffer.iter().map(|byte| format!("{:02X}", byte)).collect();
|
|
//println!("Received content (hex): {:?}", packet_hex.join(" "));
|
|
|
|
match packet_id {
|
|
0x00 => {
|
|
println!("Received Keep Alive packet (0x00)");
|
|
let response = vec![0x00]; // Not sure what to send. This might be good enough
|
|
println!("Sending a Keep Alive packet (0x00)");
|
|
stream.write(&response).unwrap();
|
|
}
|
|
0x01 => {
|
|
if size >= 18 {
|
|
// Extract protocol version (int16) and username (string16)
|
|
let protocol_version = i16::from_le_bytes([buffer[4], buffer[3]]);
|
|
let protocol_version_str = protocol_version.to_string();
|
|
let username_bytes = &buffer[8..40];
|
|
let username_str = String::from_utf8_lossy(username_bytes).to_string();
|
|
println!("Received Login packet - Protocol Version: {}, Username: {}", protocol_version_str, username_str);
|
|
|
|
if protocol_version_str == "14" {
|
|
println!("Supported protcol version {} detected!", protocol_version_str)
|
|
}
|
|
else {
|
|
println!("The detected protcol version {} isn't supported at this time. The server may not work correctly.", protocol_version_str)
|
|
}
|
|
|
|
// You can handle other fields such as Unused long and byte here if needed
|
|
|
|
// Respond as needed for the Login packet
|
|
// For example, you can check the protocol version and username and respond accordingly
|
|
|
|
// Create a response packet, for example:
|
|
//let response_packet: Vec<u8> = vec![0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
|
|
//stream.write(&response_packet).unwrap();
|
|
|
|
let response = data_dumps::DUMP0X01;
|
|
|
|
println!("Responding with a dump from java b1.7.3. (0x01)");
|
|
|
|
stream.write(&response).unwrap();
|
|
|
|
let response2 = data_dumps::DUMP0X32;
|
|
|
|
println!("Sending pre-chunk data... (0x32)");
|
|
|
|
stream.write(&response2).unwrap();
|
|
|
|
let response3 = data_dumps::DUMP0X33;
|
|
|
|
println!("Sending chunk data... (0x33)");
|
|
stream.write(&response3).unwrap();
|
|
|
|
} else {
|
|
println!("Incomplete Login packet received.");
|
|
}
|
|
}
|
|
0x02 => {
|
|
if size >= 3 {
|
|
let username_bytes = &buffer[3..];
|
|
let username_str = String::from_utf8_lossy(username_bytes).to_string();
|
|
println!("Received username: {}", username_str);
|
|
} else {
|
|
println!("Incomplete username packet received.");
|
|
}
|
|
|
|
let response = vec![0x02, 0x00, 0x01, 0x00, 0x2d];
|
|
println!("Responding with hash: {:?}", response);
|
|
|
|
stream.write(&response).unwrap();
|
|
}
|
|
0x12 => {
|
|
println!("Player most likely punched, as is only supported animation by vanilla client. (0x12)")
|
|
}
|
|
0x13 => {
|
|
println!("Player either crouched, uncrouched, or left a bed. (0x13)")
|
|
}
|
|
0x0A => {
|
|
if size >= 2 && buffer[1] == 0x01 {
|
|
println!("Player is flying. (0x0A)");
|
|
} else {
|
|
println!("Player is grounded. (0x0A)");
|
|
}
|
|
}
|
|
0x0B => {
|
|
println!("Position data sent to server. No response needed. (0x0B)");
|
|
}
|
|
0x0C => {
|
|
println!("Update where the player is looking. No response needed. (0x0C)");
|
|
}
|
|
0x0D => {
|
|
println!("Position data and look data, response needed. (0x0D)");
|
|
|
|
//Sending this causes the client to disconnect when the player looks with back packet id 64
|
|
//
|
|
//
|
|
//let response = vec![0x0d, 0x40, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50, 0xa7, 0xae, 0x14, 0x80, 0x00, 0x00, 0x40, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
|
|
//
|
|
//println!("Sending fake position + look data. (0x0D)");
|
|
//
|
|
//stream.write(&response).unwrap();
|
|
}
|
|
_ => {
|
|
println!("Received unknown packet with ID: 0x{:02X}", packet_id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let listener = TcpListener::bind("127.0.0.1:25565").expect("Failed to bind to address");
|
|
|
|
println!("Server listening on port 25565...");
|
|
|
|
for stream in listener.incoming() {
|
|
match stream {
|
|
Ok(stream) => {
|
|
thread::spawn(|| {
|
|
handle_client(stream);
|
|
});
|
|
}
|
|
Err(e) => {
|
|
eprintln!("Error accepting connection: {}", e);
|
|
}
|
|
}
|
|
}
|
|
}
|