diff --git a/client/src/hook.rs b/client/src/hook.rs index 7e83ac3..e6b4911 100644 --- a/client/src/hook.rs +++ b/client/src/hook.rs @@ -37,7 +37,12 @@ fn check_tick() { let minecraft = Minecraft::instance(); - let tick_count = match minecraft.player.entity.get_tick_count() { + let player = match minecraft.get_player() { + Ok(p) => p, + Err(_) => return, + }; + + let tick_count = match player.entity.get_tick_count() { Ok(t) => t, Err(_) => return, }; diff --git a/client/src/lib.rs b/client/src/lib.rs index a77eb57..d92d5ce 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -71,10 +71,14 @@ pub extern "C" fn initialize_client() { let mut gui_lock = gui_thread().lock().unwrap(); *gui_lock = Some(gui_handle); - info!( - "Player position: {:?}", - minecraft.player.entity.get_position() - ); + match minecraft.get_player() { + Ok(player) => { + if let Ok(pos) = player.entity.get_position() { + info!("Initial Player position: {:?}", pos); + } + } + Err(_) => info!("Client initialized, but player is not in-world yet."), + } }); } @@ -108,7 +112,7 @@ pub extern "C" fn cleanup_client() { fn register_modules(minecraft: &'static Minecraft) { let client = DarkClient::instance(); - client.register_module(FlyModule::new(minecraft.player.clone())); + client.register_module(FlyModule::new()); client.register_module(KillAuraModule::new()); client.register_module(MobAuraModule::new()); client.register_module(AimbotModule::new()); diff --git a/client/src/mapping/client/minecraft.rs b/client/src/mapping/client/minecraft.rs index a9851c0..af555e3 100644 --- a/client/src/mapping/client/minecraft.rs +++ b/client/src/mapping/client/minecraft.rs @@ -1,18 +1,19 @@ use crate::mapping::client::gamemode::MultiPlayerGameMode; use crate::mapping::client::window::Window; use crate::mapping::client::world::World; -use crate::mapping::entity::player::LocalPlayer; +use crate::mapping::entity::Entity; +use crate::mapping::entity::player::{Abilities, LocalPlayer}; use crate::mapping::{FieldType, GameContext, Mapping, MinecraftClassType}; use jni::objects::GlobalRef; use log::error; use std::ops::Deref; -use std::sync::{Arc, OnceLock}; +use std::sync::{Arc, OnceLock, RwLock}; #[derive(Debug)] pub struct Minecraft { pub jni_ref: GlobalRef, mapping: Mapping, - pub player: LocalPlayer, + player: RwLock, #[allow(dead_code)] pub world: World, pub window: Window, @@ -64,7 +65,7 @@ impl Minecraft { Ok(Minecraft { jni_ref: minecraft, mapping, - player, + player: RwLock::new(player), world, window, game_mode, @@ -74,6 +75,39 @@ impl Minecraft { pub fn get_mapping(&self) -> &Mapping { &self.mapping } + + pub fn get_player(&self) -> anyhow::Result { + let player_obj = self.mapping + .get_field( + MinecraftClassType::Minecraft, + self.jni_ref.as_obj(), + "player", + FieldType::Object(MinecraftClassType::LocalPlayer, &self.mapping), + )? + .l()?; + + if player_obj.is_null() { + return Err(anyhow::anyhow!("Player is null")); + } + + { + let read_guard = self.player.read().map_err(|_| anyhow::anyhow!("Lock poisoned"))?; + if self.mapping.get_env()?.is_same_object(&read_guard.jni_ref, &player_obj)? { + return Ok(read_guard.clone()); + } + } + + let mut write_guard = self.player.write().map_err(|_| anyhow::anyhow!("Lock poisoned"))?; + + let jni_ref = self.mapping.new_global_ref(player_obj)?; + *write_guard = LocalPlayer { + jni_ref: jni_ref.clone(), + abilities: Abilities::new(jni_ref.clone(), &self.mapping)?, + entity: Entity::new(jni_ref) + }; + + Ok(write_guard.clone()) + } } impl Deref for Minecraft { diff --git a/client/src/module/combat/aimbot.rs b/client/src/module/combat/aimbot.rs index f7466e1..4e5f71f 100644 --- a/client/src/module/combat/aimbot.rs +++ b/client/src/module/combat/aimbot.rs @@ -19,7 +19,6 @@ impl AimbotModule { category: ModuleCategory::COMBAT, key_bind: KeyboardKey::KeyC, enabled: false, - player: Minecraft::instance().player.clone(), settings: vec![ModuleSetting::Slider { name: "Range".to_string(), value: 4.0, @@ -49,7 +48,7 @@ impl Module for AimbotModule { fn on_tick(&self) -> anyhow::Result<()> { let minecraft = Minecraft::instance(); - let player = &minecraft.player; + let player = &minecraft.get_player()?; let world = &minecraft.world; let entities = world.get_entities()?; diff --git a/client/src/module/combat/aura.rs b/client/src/module/combat/aura.rs index 7022ffc..3ec77a9 100644 --- a/client/src/module/combat/aura.rs +++ b/client/src/module/combat/aura.rs @@ -22,7 +22,6 @@ impl BaseAura { category: ModuleCategory::COMBAT, key_bind, enabled: false, - player: Minecraft::instance().player.clone(), settings: vec![ModuleSetting::Slider { name: "Range".to_string(), value: 4.0, @@ -53,7 +52,7 @@ impl Module for BaseAura { fn on_tick(&self) -> anyhow::Result<()> { let minecraft = Minecraft::instance(); - let player = &minecraft.player; + let player = &minecraft.get_player()?; let world = &minecraft.world; let game_mode = &minecraft.game_mode; let mapping = minecraft.mapping(); diff --git a/client/src/module/mod.rs b/client/src/module/mod.rs index 4d3479c..5a68f43 100644 --- a/client/src/module/mod.rs +++ b/client/src/module/mod.rs @@ -40,7 +40,6 @@ pub struct ModuleData { pub category: ModuleCategory, pub key_bind: KeyboardKey, pub enabled: bool, - pub player: LocalPlayer, pub settings: Vec, } diff --git a/client/src/module/movement/fly.rs b/client/src/module/movement/fly.rs index 081eced..97f38e5 100644 --- a/client/src/module/movement/fly.rs +++ b/client/src/module/movement/fly.rs @@ -1,3 +1,4 @@ +use crate::mapping::client::minecraft::Minecraft; use crate::mapping::entity::player::LocalPlayer; use crate::module::{KeyboardKey, Module, ModuleCategory, ModuleData, ModuleSetting}; @@ -7,7 +8,7 @@ pub struct FlyModule { } impl FlyModule { - pub fn new(player: LocalPlayer) -> Self { + pub fn new() -> Self { Self { module: ModuleData { name: "Fly".to_string(), @@ -15,7 +16,6 @@ impl FlyModule { category: ModuleCategory::MOVEMENT, key_bind: KeyboardKey::KeyF, enabled: false, - player, settings: vec![ModuleSetting::Slider { name: "Speed".to_string(), value: 1.0, @@ -37,12 +37,12 @@ impl FlyModule { impl Module for FlyModule { fn on_start(&self) -> anyhow::Result<()> { // Enables flying - self.module.player.abilities.fly(true) + Minecraft::instance().get_player()?.abilities.fly(true) } fn on_stop(&self) -> anyhow::Result<()> { // Disables flying - self.module.player.abilities.fly(false) + Minecraft::instance().get_player()?.abilities.fly(false) } fn on_tick(&self) -> anyhow::Result<()> {