mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-10-19 15:13:16 +00:00
implement get_entity and get_entity_mut
This commit is contained in:
parent
2a7d3a5c46
commit
e9faa77b28
4 changed files with 37 additions and 48 deletions
|
@ -7,8 +7,7 @@ use eyre::{Context, OptionExt, bail};
|
|||
use modules::{Module, ModuleCtx, entity_sync::EntitySync};
|
||||
use net::NetManager;
|
||||
use noita_api::add_lua_fn;
|
||||
use noita_api::addr_grabber::{grab_addrs, grabbed_fns, grabbed_globals};
|
||||
use noita_api::noita::types::Entity;
|
||||
use noita_api::addr_grabber::{grab_addrs, grabbed_globals};
|
||||
use noita_api::noita::world::ParticleWorldState;
|
||||
use noita_api::{
|
||||
DamageModelComponent, EntityID, VariableStorageComponent,
|
||||
|
@ -20,8 +19,6 @@ use noita_api::{
|
|||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use shared::des::{Gid, RemoteDes};
|
||||
use shared::{Destination, NoitaInbound, NoitaOutbound, PeerId, SpawnOnce, WorldPos};
|
||||
#[cfg(target_arch = "x86")]
|
||||
use std::arch::asm;
|
||||
use std::array::IntoIter;
|
||||
use std::backtrace::Backtrace;
|
||||
use std::mem::MaybeUninit;
|
||||
|
@ -156,26 +153,12 @@ fn init_particle_world_state(lua: LuaState) -> eyre::Result<()> {
|
|||
|
||||
pub fn ephemerial(entity_id: u32) -> eyre::Result<()> {
|
||||
unsafe {
|
||||
let entity_manager = grabbed_globals().entity_manager.read();
|
||||
let entity: *mut Entity;
|
||||
#[cfg(target_arch = "x86")]
|
||||
asm!(
|
||||
"mov ecx, {entity_manager}",
|
||||
"push {entity_id:e}",
|
||||
"call {get_entity}",
|
||||
entity_manager = in(reg) entity_manager,
|
||||
get_entity = in(reg) grabbed_fns().get_entity,
|
||||
entity_id = in(reg) entity_id,
|
||||
clobber_abi("C"),
|
||||
out("ecx") _,
|
||||
out("eax") entity,
|
||||
);
|
||||
#[cfg(not(target_arch = "x86"))]
|
||||
let entity_manager = grabbed_globals().entity_manager.as_ref().unwrap();
|
||||
if let Some(entity) = entity_manager
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_entity_mut(entity_id as isize)
|
||||
{
|
||||
std::hint::black_box((entity_manager, grabbed_fns().get_entity));
|
||||
entity = Default::default();
|
||||
}
|
||||
if let Some(entity) = entity.as_mut() {
|
||||
entity.filename_index = 0;
|
||||
} else {
|
||||
bail!("Entity {entity_id} not found");
|
||||
|
|
|
@ -15,14 +15,12 @@ impl Module for WorldSync {
|
|||
runs: Vec::with_capacity(16384),
|
||||
};
|
||||
let mut upd = std::array::from_fn(|_| None);
|
||||
let time = std::time::Instant::now();
|
||||
unsafe {
|
||||
self.particle_world_state
|
||||
.assume_init_ref()
|
||||
.encode_world(ChunkCoord(-2, -7), &mut upd)?;
|
||||
}
|
||||
std::hint::black_box(upd);
|
||||
noita_api::print!("{:?}", time.elapsed().as_micros());
|
||||
let msg = NoitaOutbound::WorldSyncToProxy(WorldSyncToProxy::Updates(vec![update]));
|
||||
ctx.net.send(&msg)?;
|
||||
Ok(())
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::{mem, os::raw::c_void, ptr, sync::OnceLock};
|
||||
use std::{os::raw::c_void, ptr, sync::OnceLock};
|
||||
|
||||
use crate::lua::LuaState;
|
||||
use crate::noita::types::{EntityManager, ThiscallFn};
|
||||
use crate::noita::types::EntityManager;
|
||||
use iced_x86::{Decoder, DecoderOptions, Mnemonic};
|
||||
static GRABBED: OnceLock<Grabbed> = OnceLock::new();
|
||||
|
||||
|
@ -32,7 +32,6 @@ pub(crate) unsafe fn grab_addr_from_instruction(
|
|||
|
||||
struct Grabbed {
|
||||
globals: GrabbedGlobals,
|
||||
fns: GrabbedFns,
|
||||
}
|
||||
|
||||
// This only stores pointers that are constant, so should be safe to share between threads.
|
||||
|
@ -44,36 +43,20 @@ pub struct GrabbedGlobals {
|
|||
pub entity_manager: *const *mut EntityManager,
|
||||
}
|
||||
|
||||
pub struct GrabbedFns {
|
||||
pub get_entity: *const ThiscallFn, //unsafe extern "C" fn(*const EntityManager, u32) -> *mut Entity,
|
||||
}
|
||||
|
||||
pub fn grab_addrs(lua: LuaState) {
|
||||
lua.get_global(c"EntityGetFilename");
|
||||
let base = lua.to_cfunction(-1).unwrap() as *const c_void;
|
||||
let get_entity = unsafe {
|
||||
mem::transmute_copy(&grab_addr_from_instruction(
|
||||
base,
|
||||
0x0079782b - 0x00797570,
|
||||
Mnemonic::Call,
|
||||
))
|
||||
};
|
||||
let entity_manager =
|
||||
let entity_manager: *const *mut EntityManager =
|
||||
unsafe { grab_addr_from_instruction(base, 0x00797821 - 0x00797570, Mnemonic::Mov).cast() };
|
||||
lua.pop_last();
|
||||
|
||||
GRABBED
|
||||
.set(Grabbed {
|
||||
globals: GrabbedGlobals { entity_manager },
|
||||
fns: GrabbedFns { get_entity },
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
|
||||
pub fn grabbed_fns() -> &'static GrabbedFns {
|
||||
&GRABBED.get().expect("to be initialized early").fns
|
||||
}
|
||||
|
||||
pub fn grabbed_globals() -> &'static GrabbedGlobals {
|
||||
&GRABBED.get().expect("to be initialized early").globals
|
||||
}
|
||||
|
|
|
@ -918,15 +918,40 @@ pub struct GameGlobal {
|
|||
pub pause_state: isize,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct Entity {
|
||||
_unknown0: [u8; 8],
|
||||
pub filename_index: u32,
|
||||
pub id: isize,
|
||||
pub entry: isize,
|
||||
pub filename_index: usize,
|
||||
//TODO More stuff, not that relevant currently.
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct EntityManager {
|
||||
_fld: c_void,
|
||||
unknown: [isize; 5],
|
||||
pub list: *mut *mut Entity,
|
||||
pub last: usize,
|
||||
unknown2: [isize; 120],
|
||||
//TODO Unknown
|
||||
}
|
||||
|
||||
impl EntityManager {
|
||||
pub fn get_entity(&self, id: isize) -> Option<&'static Entity> {
|
||||
let len = (self.last - self.list as usize) / 4;
|
||||
let start = unsafe { self.list.offset(id - 1) };
|
||||
let list = unsafe { std::slice::from_raw_parts(start, len - id as usize) };
|
||||
list.iter()
|
||||
.find_map(|c| unsafe { c.as_ref() }.filter(|c| c.id == id))
|
||||
}
|
||||
pub fn get_entity_mut(&self, id: isize) -> Option<&'static mut Entity> {
|
||||
let len = (self.last - self.list as usize) / 4;
|
||||
let start = unsafe { self.list.offset(id - 1) };
|
||||
let list = unsafe { std::slice::from_raw_parts(start, len - id as usize) };
|
||||
list.iter()
|
||||
.find_map(|c| unsafe { c.as_mut() }.filter(|c| c.id == id))
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ThiscallFn(c_void);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue