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 modules::{Module, ModuleCtx, entity_sync::EntitySync};
|
||||||
use net::NetManager;
|
use net::NetManager;
|
||||||
use noita_api::add_lua_fn;
|
use noita_api::add_lua_fn;
|
||||||
use noita_api::addr_grabber::{grab_addrs, grabbed_fns, grabbed_globals};
|
use noita_api::addr_grabber::{grab_addrs, grabbed_globals};
|
||||||
use noita_api::noita::types::Entity;
|
|
||||||
use noita_api::noita::world::ParticleWorldState;
|
use noita_api::noita::world::ParticleWorldState;
|
||||||
use noita_api::{
|
use noita_api::{
|
||||||
DamageModelComponent, EntityID, VariableStorageComponent,
|
DamageModelComponent, EntityID, VariableStorageComponent,
|
||||||
|
@ -20,8 +19,6 @@ use noita_api::{
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use shared::des::{Gid, RemoteDes};
|
use shared::des::{Gid, RemoteDes};
|
||||||
use shared::{Destination, NoitaInbound, NoitaOutbound, PeerId, SpawnOnce, WorldPos};
|
use shared::{Destination, NoitaInbound, NoitaOutbound, PeerId, SpawnOnce, WorldPos};
|
||||||
#[cfg(target_arch = "x86")]
|
|
||||||
use std::arch::asm;
|
|
||||||
use std::array::IntoIter;
|
use std::array::IntoIter;
|
||||||
use std::backtrace::Backtrace;
|
use std::backtrace::Backtrace;
|
||||||
use std::mem::MaybeUninit;
|
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<()> {
|
pub fn ephemerial(entity_id: u32) -> eyre::Result<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let entity_manager = grabbed_globals().entity_manager.read();
|
let entity_manager = grabbed_globals().entity_manager.as_ref().unwrap();
|
||||||
let entity: *mut Entity;
|
if let Some(entity) = entity_manager
|
||||||
#[cfg(target_arch = "x86")]
|
.as_ref()
|
||||||
asm!(
|
.unwrap()
|
||||||
"mov ecx, {entity_manager}",
|
.get_entity_mut(entity_id as isize)
|
||||||
"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"))]
|
|
||||||
{
|
{
|
||||||
std::hint::black_box((entity_manager, grabbed_fns().get_entity));
|
|
||||||
entity = Default::default();
|
|
||||||
}
|
|
||||||
if let Some(entity) = entity.as_mut() {
|
|
||||||
entity.filename_index = 0;
|
entity.filename_index = 0;
|
||||||
} else {
|
} else {
|
||||||
bail!("Entity {entity_id} not found");
|
bail!("Entity {entity_id} not found");
|
||||||
|
|
|
@ -15,14 +15,12 @@ impl Module for WorldSync {
|
||||||
runs: Vec::with_capacity(16384),
|
runs: Vec::with_capacity(16384),
|
||||||
};
|
};
|
||||||
let mut upd = std::array::from_fn(|_| None);
|
let mut upd = std::array::from_fn(|_| None);
|
||||||
let time = std::time::Instant::now();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.particle_world_state
|
self.particle_world_state
|
||||||
.assume_init_ref()
|
.assume_init_ref()
|
||||||
.encode_world(ChunkCoord(-2, -7), &mut upd)?;
|
.encode_world(ChunkCoord(-2, -7), &mut upd)?;
|
||||||
}
|
}
|
||||||
std::hint::black_box(upd);
|
std::hint::black_box(upd);
|
||||||
noita_api::print!("{:?}", time.elapsed().as_micros());
|
|
||||||
let msg = NoitaOutbound::WorldSyncToProxy(WorldSyncToProxy::Updates(vec![update]));
|
let msg = NoitaOutbound::WorldSyncToProxy(WorldSyncToProxy::Updates(vec![update]));
|
||||||
ctx.net.send(&msg)?;
|
ctx.net.send(&msg)?;
|
||||||
Ok(())
|
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::lua::LuaState;
|
||||||
use crate::noita::types::{EntityManager, ThiscallFn};
|
use crate::noita::types::EntityManager;
|
||||||
use iced_x86::{Decoder, DecoderOptions, Mnemonic};
|
use iced_x86::{Decoder, DecoderOptions, Mnemonic};
|
||||||
static GRABBED: OnceLock<Grabbed> = OnceLock::new();
|
static GRABBED: OnceLock<Grabbed> = OnceLock::new();
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ pub(crate) unsafe fn grab_addr_from_instruction(
|
||||||
|
|
||||||
struct Grabbed {
|
struct Grabbed {
|
||||||
globals: GrabbedGlobals,
|
globals: GrabbedGlobals,
|
||||||
fns: GrabbedFns,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This only stores pointers that are constant, so should be safe to share between threads.
|
// 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 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) {
|
pub fn grab_addrs(lua: LuaState) {
|
||||||
lua.get_global(c"EntityGetFilename");
|
lua.get_global(c"EntityGetFilename");
|
||||||
let base = lua.to_cfunction(-1).unwrap() as *const c_void;
|
let base = lua.to_cfunction(-1).unwrap() as *const c_void;
|
||||||
let get_entity = unsafe {
|
let entity_manager: *const *mut EntityManager =
|
||||||
mem::transmute_copy(&grab_addr_from_instruction(
|
|
||||||
base,
|
|
||||||
0x0079782b - 0x00797570,
|
|
||||||
Mnemonic::Call,
|
|
||||||
))
|
|
||||||
};
|
|
||||||
let entity_manager =
|
|
||||||
unsafe { grab_addr_from_instruction(base, 0x00797821 - 0x00797570, Mnemonic::Mov).cast() };
|
unsafe { grab_addr_from_instruction(base, 0x00797821 - 0x00797570, Mnemonic::Mov).cast() };
|
||||||
lua.pop_last();
|
lua.pop_last();
|
||||||
|
|
||||||
GRABBED
|
GRABBED
|
||||||
.set(Grabbed {
|
.set(Grabbed {
|
||||||
globals: GrabbedGlobals { entity_manager },
|
globals: GrabbedGlobals { entity_manager },
|
||||||
fns: GrabbedFns { get_entity },
|
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn grabbed_fns() -> &'static GrabbedFns {
|
|
||||||
&GRABBED.get().expect("to be initialized early").fns
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn grabbed_globals() -> &'static GrabbedGlobals {
|
pub fn grabbed_globals() -> &'static GrabbedGlobals {
|
||||||
&GRABBED.get().expect("to be initialized early").globals
|
&GRABBED.get().expect("to be initialized early").globals
|
||||||
}
|
}
|
||||||
|
|
|
@ -918,15 +918,40 @@ pub struct GameGlobal {
|
||||||
pub pause_state: isize,
|
pub pause_state: isize,
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Entity {
|
pub struct Entity {
|
||||||
_unknown0: [u8; 8],
|
pub id: isize,
|
||||||
pub filename_index: u32,
|
pub entry: isize,
|
||||||
|
pub filename_index: usize,
|
||||||
//TODO More stuff, not that relevant currently.
|
//TODO More stuff, not that relevant currently.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct EntityManager {
|
pub struct EntityManager {
|
||||||
_fld: c_void,
|
unknown: [isize; 5],
|
||||||
|
pub list: *mut *mut Entity,
|
||||||
|
pub last: usize,
|
||||||
|
unknown2: [isize; 120],
|
||||||
//TODO Unknown
|
//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)]
|
#[repr(C)]
|
||||||
pub struct ThiscallFn(c_void);
|
pub struct ThiscallFn(c_void);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue