Arrow-rs/src/main.rs
2023-10-15 21:03:34 -06:00

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);
}
}
}
}