From f8312c022991673b64d9d6051b8b348ecf6d9a7d Mon Sep 17 00:00:00 2001 From: illegitimate-egg Date: Wed, 12 Jun 2024 18:32:05 +0100 Subject: [PATCH] Will pls fix mutex lmao --- Cargo.lock | 110 +++++++++++ Cargo.toml | 3 + src/main.rs | 523 ++++++++++++++++++++++++++++++++++++++------------- src/world.gz | Bin 0 -> 152 bytes 4 files changed, 509 insertions(+), 127 deletions(-) create mode 100644 src/world.gz diff --git a/Cargo.lock b/Cargo.lock index 4ea5480..f89e8c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,116 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + [[package]] name = "mcrizzledizzle" version = "0.1.0" +dependencies = [ + "flate2", + "lazy_static", + "rand", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +dependencies = [ + "adler", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/Cargo.toml b/Cargo.toml index aec0f5f..d017616 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] +flate2 = "1.0.30" +lazy_static = "1.4.0" +rand = "0.8.5" diff --git a/src/main.rs b/src/main.rs index a827256..de00923 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,151 +1,416 @@ use std::io::prelude::*; use std::net::{TcpListener, TcpStream}; +use std::ops::DerefMut; use std::thread::sleep; use std::time::Duration; use std::thread; +use std::sync::{Arc, Mutex}; +use std::sync::mpsc::{channel, Receiver}; +use flate2::Compression; +use flate2::write::GzEncoder; +use rand::prelude::*; +#[macro_use] +extern crate lazy_static; + +impl Default for Player { + fn default() -> Self { + Player { + id: SpecialPlayers::SelfPlayer as u8, + username: "".to_string(), + verification_key: [0; 64], + unused: 0x00, + position_x: 0, + position_y: 0, + position_z: 0, + yaw: 0, + pitch: 0, + operator: false + } + } +} + +struct Player { // Struct `Player` is never constructed `#[warn(fuck_you)]` on by default + pub id: u8, + pub username: String, + pub verification_key: [u8; 64], + pub unused: u8, + pub position_x: i16, + pub position_y: i16, + pub position_z: i16, + pub yaw: u8, + pub pitch: u8, + pub operator: bool +} + +enum SpecialPlayers { + SelfPlayer = 0xFF +} + +struct World { + pub size_x: i16, + pub size_y: i16, + pub size_z: i16, + pub data: Vec +} + +fn build_world(size_x: i16, size_y: i16, size_z: i16) -> Vec { + let mut rng = rand::thread_rng(); + + let mut world_dat: Vec = Vec::new(); + + for y in 0..size_y { + for _z in 0..size_z { + for _x in 0..size_x { + if y == 0 { + world_dat.push(rng.gen()); // Bookshelf + } else { + world_dat.push(rng.gen::() % 0x31); // Air + } + } + } + } + + return world_dat; +} + +const SIZE_X: i16 = 512; +const SIZE_Y: i16 = 128; +const SIZE_Z: i16 = 512; + +lazy_static!{ + static ref WORLD: World = World { + size_x: SIZE_X, + size_y: SIZE_Y, + size_z: SIZE_Z, + data: build_world(SIZE_X, SIZE_Y, SIZE_Z) + }; + + static ref PLAYER_DB: [Arc>; 255] = core::array::from_fn(|_| Arc::new(Mutex::new(Player::default()))); +} + + +fn get_player(id: u8) -> Receiver { + let data = Arc::clone(&PLAYER_DB[id as usize]); + let (tx, rx) = channel::(); + let mut data = data.lock().unwrap(); + tx.send(data); + return rx; +} fn handle_client(mut stream: TcpStream, client_number: u8) { thread::spawn(move || { - let mut buffer = [0; 256]; - let _ = stream.read(&mut buffer); -// let _ = stream.write(&[8]); + let mut master_rot = 0; - match buffer[0] { - 0x00=> { - println!("Client Prot Ver: {}", buffer[1]); - let mut username = String::new(); + loop { + let mut buffer = [0; 1]; + let _ = stream.read(&mut buffer); - for i in 0..64 { - username.push(buffer[i+2] as char); + let mut current_player = &mut PLAYER_DB[client_number as usize]; + + match buffer[0] { + 0x00=> { + let mut payload_buffer = [0; 130]; // Byte + String + String + Byte + let _ = stream.read(&mut payload_buffer); + + if payload_buffer[0] != 7 { + // Shit pant + let _ = client_disconnect(&mut stream, "Something went wrong (CODE: PACKET_SKIPPED)"); + println!("THIS CLIENT IS FUCKED!"); + break; + } + + println!("Client Prot Ver: {}", payload_buffer[0]); + let mut username = String::new(); + + for i in 0..64 { + username.push(payload_buffer[i+1] as char); + } + println!("Username: {}", username); + + let mut verif_key = [0; 64]; + + for i in 0..64 { + verif_key[i] = payload_buffer[i+65]; + } + + let mut verif_key_formatted = String::new(); + use std::fmt::Write; + for &byte in &verif_key { + write!(&mut verif_key_formatted, "{:X}", byte).expect("Piss"); + } + + println!("Verification key: 0x{}", verif_key_formatted); + + println!("\"Unused\" Byte: {}", payload_buffer[129]); + + current_player.id = current_player; + current_player.username = username; + current_player.verification_key = verif_key; + current_player.unused = payload_buffer[129]; + current_player.position_x = 0; + current_player.position_y = 128; + current_player.position_z = 0; + current_player.yaw = 0; + current_player.pitch = 0; + current_player.operator = false; + + bomb_server_details(&mut stream, current_player); + }, + 0x08=>{ + let mut payload_buffer = [0; 9]; // SByte + FShort (2B) + FShort + FShort + + // Byte + Byte + let _ = stream.read(&mut payload_buffer); + + if payload_buffer[0] != SpecialPlayers::SelfPlayer as u8 { + let _ = client_disconnect(&mut stream, "Evil bit level hacking"); + break; + } + + current_player.position_x = ((payload_buffer[1] as i16) << (8 as i16)) + payload_buffer[2] as i16; + current_player.position_y = ((payload_buffer[3] as i16) << (8 as i16)) + payload_buffer[4] as i16; + current_player.position_z = ((payload_buffer[5] as i16) << (8 as i16)) + payload_buffer[6] as i16; + + current_player.yaw = payload_buffer[7]; + current_player.pitch = payload_buffer[8]; + }, + 0x0D=>{ + let mut payload_buffer = [0; 65]; // Byte + String + let _ = stream.read(&mut payload_buffer); + + if payload_buffer[0] != SpecialPlayers::SelfPlayer as u8 { + let _ = client_disconnect(&mut stream, "Evil bit level hacking"); + break; + } + + let mut message = ['a'; 64]; + for i in 0..64 { + message[i] = payload_buffer[i+1] as char; + } + + let _ = send_chat_message(&mut stream, SpecialPlayers::SelfPlayer as u8, String::from_iter(message)); + println!("{}", String::from_iter(message)); + }, + _=>println!("Packet {} not implemented!", buffer[0]), } - println!("Username: {}", username); - - let mut verif_key = [0; 64]; - - for i in 0..64 { - verif_key[i] = buffer[i+66]; - } - - let mut verif_key_formatted = String::new(); - use std::fmt::Write; - for &byte in &verif_key { - write!(&mut verif_key_formatted, "{:X}", byte).expect("Piss"); - } - - println!("Verification key: 0x{}", verif_key_formatted); - - println!("\"Unused\" Byte: {}", buffer[130]); - bomb_server_details(stream, client_number) - }, - _=>println!("Mindfield"), - } - }); -} - -fn to_mc_string(text: &str) -> [u8; 64] { - let text_vec: Vec = text.chars().collect(); - let mut balls = [0; 64]; - - for i in 0..64 { - balls[i] = 0x20; - } - - for i in 0..text.len() { - balls[i] = text_vec[i] as u8; - } - - return balls; -} - -fn bomb_server_details(mut stream: TcpStream, client_number: u8) { - let _ = stream.write(&[0]); // Server IDENT - println!("Server IDENT"); - let _ = stream.write(&[0x07]); // Protocol version 7 - println!("Server protocol ver: 7"); - - let server_name = format!("Sigma Balls {}", client_number); - for i in 0..64 { - let _ = stream.write(&[to_mc_string(&server_name)[i]]); // Send server name - } - println!("Server name: {}", server_name); - - let motd = "Pragmatism not idealism"; - for i in 0..64 { - let _ = stream.write(&[to_mc_string(&motd)[i]]); // Send server name - } - println!("MOTD: {}", motd); - - let _ = stream.write(&[0x64]); - println!("Player is an OP (shits pants)"); - //let _ = stream.write(&[0x01]); // Ping the rizzler - let _ = stream.write(&[0x02]); // Init level - // Shit must be sent here (Shits pants) - let _ = stream.write(&[0x04]); // Finalize level - let _ = stream.write(&[0xFF]); // Level Size X - let _ = stream.write(&[0xFF]); // Level Size X B2 - let _ = stream.write(&[0xFF]); // Height Limit - let _ = stream.write(&[0xFF]); // Height Limit B2 - let _ = stream.write(&[0xFF]); // Level Size Z - let _ = stream.write(&[0xFF]); // Level Size Z B2 - let _ = stream.write(&[0x07]); // Spawn player - let _ = stream.write(&[0x01]); // Player ID - let name = format!("Ultra {}", client_number); - for i in 0..64 { // Send player name - let _ = stream.write(&[to_mc_string(&name)[i]]); // Send server name - } - let _ = stream.write(&[0x00]); // Spawn X - let _ = stream.write(&[0x00]); // Spawn X B2 - let _ = stream.write(&[0x00]); // Spawn Y - let _ = stream.write(&[0x00]); // Spawn Y B2 - let _ = stream.write(&[0x00]); // Spawn Z - let _ = stream.write(&[0x00]); // Spawn Z B2 - let _ = stream.write(&[0x00]); // Spawn YAW - let _ = stream.write(&[0x00]); // Spawn PITCH - - let _ = stream.write(&[0x01]); - let _ = stream.write(&[0x01]); - let _ = stream.write(&[0x01]); - - let mut mega_rizma_test_one : u8 = 1; - - loop { - let is_kill = stream.write(&[0x01]); // Ping that MF + let is_kill = ping(&mut stream); // Ping that MF if is_kill.is_err() { println!("Thread {} is kill!", client_number); break; } - let _ = stream.write(&[0x07]); // Spawn player - let _ = stream.write(&[mega_rizma_test_one]); // Player ID - let nameb = format!("Brizinga {}", mega_rizma_test_one); - for i in 0..64 { // Send player name - let _ = stream.write(&[to_mc_string(&nameb)[i]]); // Send server name - } - let _ = stream.write(&[mega_rizma_test_one << 5]); // Spawn X - let _ = stream.write(&[0x00]); // Spawn X B2 - let _ = stream.write(&[0x00]); // Spawn Y - let _ = stream.write(&[0x00]); // Spawn Y B2 - let _ = stream.write(&[0x00]); // Spawn Z - let _ = stream.write(&[0x00]); // Spawn Z B2 - let _ = stream.write(&[0x00]); // Spawn YAW - let _ = stream.write(&[0x00]); // Spawn PITCH - - let _ = stream.write(&[0x0D]); - let _ = stream.write(&[0x01]); // Player ID - for i in 0..64 { // Send player name - let _ = stream.write(&[to_mc_string(&nameb)[i]]); // Send server name + for i in 0..254 { + let _ = orientation_update(&mut stream, i, (((i as u16 + master_rot as u16) % 255)) as u8, 0); } - println!("Player position updated, test = {}", mega_rizma_test_one); - - if mega_rizma_test_one != 254 { - mega_rizma_test_one += 1; + if master_rot != 255 { + master_rot += 1; } else { - mega_rizma_test_one = 0; + master_rot = 0; } - //sleep(Duration::from_millis(10)); + sleep(Duration::from_millis(50)); + } + }); +} + +fn to_mc_string(text: &str) -> [u8; 64] { + let text_vec: Vec = text.chars().take(64).collect(); + let mut balls = [0; 64]; + + for i in 0..64 { + balls[i] = 0x20; + } + + for i in 0..text_vec.len() { + balls[i] = text_vec[i] as u8; + } + + return balls; +} + +fn stream_write_array(data: &[u8], stream: &mut TcpStream) -> std::io::Result<()> { + for i in 0..data.len() { + stream.write(&[data[i]])?; + } + Ok(()) +} + +fn stream_write_short(data: i16, stream: &mut TcpStream) -> std::io::Result<()> { + stream.write(&[(data >> 0x08) as u8])?; + stream.write(&[(data & 0x00FF) as u8])?; + + Ok(()) +} + +fn client_disconnect(stream: &mut TcpStream, text: &str) -> std::io::Result<()> { + stream.write(&[0x0E])?; // Disconnect + stream_write_array(&to_mc_string(text), stream)?; + + Ok(()) +} + +fn server_identification(stream: &mut TcpStream, is_op: bool) -> std::io::Result<()> { + stream.write(&[0x00])?; + stream.write(&[0x07])?; + + let server_name = "Erm... what the sigma?"; + stream_write_array(&to_mc_string(server_name), stream)?; + + let server_motd = "Pragmatism not idealism"; + stream_write_array(&to_mc_string(server_motd), stream)?; + + if is_op { + stream.write(&[0x64])?; + } else { + stream.write(&[0x00])?; + } + + Ok(()) +} + +fn ping (stream: &mut TcpStream) -> std::io::Result<()> { + stream.write(&[0x01])?; + + Ok(()) +} + +fn init_level(stream: &mut TcpStream) -> std::io::Result<()> { + stream.write(&[0x02])?; + + Ok(()) +} + +fn finalize_level(stream: &mut TcpStream, size_x: i16, size_y: i16, size_z: i16) -> std::io::Result<()> { + stream.write(&[0x04])?; + + stream_write_short(size_x, stream)?; + stream_write_short(size_y, stream)?; + stream_write_short(size_z, stream)?; + + Ok(()) +} + +fn spawn_player(stream: &mut TcpStream, player_id: u8, name: &String, pos_x: i16, pos_y: i16, pos_z: i16, yaw: u8, pitch: u8) -> std::io::Result<()> { + stream.write(&[0x07])?; + + stream.write(&[player_id])?; + stream_write_array(&to_mc_string(name), stream)?; + stream_write_short(pos_x << 5, stream)?; + stream_write_short(pos_y << 5, stream)?; + stream_write_short(pos_z << 5, stream)?; + stream.write(&[yaw])?; + stream.write(&[pitch])?; + + Ok(()) +} + +fn send_chat_message(stream: &mut TcpStream, source_id: u8, message: String) -> std::io::Result<()> { + stream.write(&[0x0D])?; + + stream.write(&[source_id])?; + stream_write_array(&to_mc_string(&message), stream)?; + + Ok(()) +} + +fn orientation_update(stream: &mut TcpStream, player_id: u8, yaw: u8, pitch: u8) -> std::io::Result<()> { + stream.write(&[0x0B])?; + + stream.write(&[player_id])?; + stream.write(&[yaw])?; + stream.write(&[pitch])?; + + Ok(()) +} + +fn send_level_data(stream: &mut TcpStream) -> std::io::Result<()> { + let mut world_dat = WORLD.data.clone(); + + // Big endian fold lmao + world_dat.insert(0, ((world_dat.len() & 0xFF) >> 0) as u8); + world_dat.insert(0, ((world_dat.len() & 0xFF00) >> 8) as u8); + world_dat.insert(0, ((world_dat.len() & 0xFF0000) >> 16) as u8); + world_dat.insert(0, ((world_dat.len() & 0xFF000000) >> 24) as u8); + + // TODO: Stream GZIP straight onto the network + + let mut world_dat_compressor = GzEncoder::new(Vec::new(), Compression::fast()); + for i in 0..world_dat.len() { + let _ = world_dat_compressor.write(&[world_dat[i]]); + } + let world_dat_gzipped = world_dat_compressor.finish().unwrap(); + + let number_of_chunks = ((world_dat_gzipped.len() as f32)/1024.0_f32).ceil() as usize; + let mut current_chunk = 0; + + if number_of_chunks != 1 { + while current_chunk + 1 != number_of_chunks { + stream.write(&[0x03])?; + + stream_write_short(0x400, stream)?; + + let mut chunk_data_buffer = [0u8; 1024]; + for i in 0..1024 { + chunk_data_buffer[i] = world_dat_gzipped[current_chunk*1024+i]; + } + stream_write_array(&chunk_data_buffer, stream)?; + + let mut percentage = current_chunk/number_of_chunks*100; + + if percentage > 100 { + percentage = 100; + } + + stream.write(&[percentage.try_into().unwrap()])?; + + current_chunk += 1; + } + } + + let remaining_chunk_size = world_dat_gzipped.len() - (current_chunk * 1024); + + if remaining_chunk_size > 0 { + stream.write(&[0x03])?; + + stream_write_short(remaining_chunk_size.try_into().unwrap(), stream)?; + + let mut remaining_data_buffer = [0u8; 1024]; + for i in 0..remaining_chunk_size { + remaining_data_buffer[i] = world_dat_gzipped[current_chunk*1024+i]; + } + + stream_write_array(&remaining_data_buffer, stream)?; + stream.write(&[100])?; + } + + Ok(()) +} + +fn bomb_server_details(stream: &mut TcpStream, current_player: &Player) { + println!("Server IDENT"); + let _ = server_identification(stream, current_player.operator); + + println!("Intialize level"); + let _ = init_level(stream); + + println!("Send level data"); + let _ = send_level_data(stream); // Approaching Nirvana - Maw of the beast + + println!("Finalize level"); + let _ = finalize_level(stream, WORLD.size_x, WORLD.size_y, WORLD.size_z); + + println!("Spawning player"); + + let _ = spawn_player(stream, SpecialPlayers::SelfPlayer as u8, ¤t_player.username, 64, 2, 64, 0, 0); + + println!("Ping 3 times (idfk why we do this)"); + let _ = ping(stream); + let _ = ping(stream); + let _ = ping(stream); + + for i in 0..254 { + let _ = spawn_player(stream, i, &format!("Test {}", i), (i % 15).into(), 2, (i / 17).into(), i, 0); } } @@ -156,7 +421,11 @@ fn main() -> std::io::Result<()> { for stream in listener.incoming() { handle_client(stream?, thread_number); - thread_number += 1; + if thread_number < 255 { + thread_number += 1; + } else { + thread_number = 0; + } } Ok(()) } diff --git a/src/world.gz b/src/world.gz new file mode 100644 index 0000000000000000000000000000000000000000..bf8bbf12adfe8f849ad86184cee8d9eec7961c37 GIT binary patch literal 152 zcmb2|=3oGW|8EZ{GBOx&Fl^Y(ociK^A4|oNFv