diff --git a/ewext/src/lib.rs b/ewext/src/lib.rs index 5e2715bf..771ef463 100644 --- a/ewext/src/lib.rs +++ b/ewext/src/lib.rs @@ -1,6 +1,12 @@ -use std::{ffi::c_int, sync::LazyLock}; +use std::{ + borrow::BorrowMut, + cell::{LazyCell, RefCell}, + ffi::{c_int, c_void}, + sync::{LazyLock, Mutex}, +}; use lua_bindings::{lua_State, Lua51}; +use noita::ParticleWorldState; mod lua_bindings; @@ -11,39 +17,29 @@ static LUA: LazyLock = LazyLock::new(|| unsafe { Lua51::from_library(lib).expect("library to be lua") }); +thread_local! { + static STATE: LazyCell = LazyCell::new(|| ExtState::default()); +} + +#[derive(Default)] +struct ExtState { + particle_world_state: Option, +} + // const EWEXT: [(&'static str, Function); 1] = [("testfn", None)]; -extern "C" fn test_fn(_lua: *mut lua_State) -> c_int { - println!("\nStarting trace"); - backtrace::trace(|frame| { - // let ip = frame.ip(); - let symbol_address = frame.symbol_address(); +extern "C" fn init_particle_world_state(lua: *mut lua_State) -> c_int { + println!("\nInitializing particle world state"); + let world_pointer = unsafe { LUA.lua_tointeger(lua, 1) }; + let chunk_map_pointer = unsafe { LUA.lua_tointeger(lua, 2) }; + println!("pws stuff: {world_pointer:?} {chunk_map_pointer:?}"); - print!("symbol: {:#08X}", symbol_address as usize); - if let Some(base) = frame.module_base_address() { - print!(" base: {:#08X}", base as usize); - } - // Resolve this instruction pointer to a symbol name - backtrace::resolve_frame(frame, |symbol| { - if let Some(name) = symbol.name() { - print!(" name: {name}"); - } - if let Some(filename) = symbol.filename() { - print!(" file: {}", filename.display()); - } - }); - println!(); - - for i in 0..16 { - let b: u8 = - unsafe { std::ptr::read_volatile((symbol_address as *const u8).wrapping_add(i)) }; - print!("{:02X} ", b); - } - println!(); - - true // keep going to the next frame + STATE.with(|mut state| { + state.particle_world_state = Some(ParticleWorldState::new( + world_pointer as *mut c_void, + chunk_map_pointer as *mut c_void, + )) }); - println!("End trace\n"); 0 } @@ -51,10 +47,11 @@ extern "C" fn test_fn(_lua: *mut lua_State) -> c_int { pub extern "C" fn luaopen_ewext(lua: *mut lua_State) -> c_int { println!("Initializing ewext"); unsafe { - LUA.lua_pushcclosure(lua, Some(test_fn), 0); - // LUA.lua_setfield(lua, LUA_GLOBALSINDEX, c"ewext".as_ptr()) + LUA.lua_createtable(lua, 0, 0); + + LUA.lua_pushcclosure(lua, Some(init_particle_world_state), 0); + LUA.lua_setfield(lua, -2, c"init_particle_world_state".as_ptr()); } - // let mut luastate = unsafe { State::from_ptr(luastateptr) }; - // luastate.new_lib(&EWEXT); + println!("Initializing ewext - Ok"); 1 } diff --git a/ewext/src/noita.rs b/ewext/src/noita.rs index 2425cb40..33ab8453 100644 --- a/ewext/src/noita.rs +++ b/ewext/src/noita.rs @@ -1,16 +1,29 @@ use std::ffi::c_void; -pub(crate) struct ChunkMap { - this: *mut c_void, +pub(crate) struct ParticleWorldState { + world_pointer: *mut c_void, + chunk_map_this: *mut c_void, } -impl ChunkMap { - unsafe fn get_cell(&self, x: u32, y: u32) { +impl ParticleWorldState { + unsafe fn get_cell(&self, x: u32, y: u32) -> *const c_void { let x = x as isize; let y = y as isize; - let index = ((((y) >> 9) - 256 & 511) * 512 + (((x) >> 9) - 256 & 511)) * 4; - let chunk_arr = self.this.offset(8).cast::<*const c_void>().read(); - let chunk = chunk_arr.offset(index).cast::<*const c_void>().read(); + let chunk_index = (((((y) >> 9) - 256) & 511) * 512 + ((((x) >> 9) - 256) & 511)) * 4; + let chunk_arr = self + .chunk_map_this + .offset(8) + .cast::<*const *const c_void>() + .read(); + let chunk = chunk_arr.offset(chunk_index).read(); let pixel = chunk.offset(((y & 511) << 9 | x & 511) * 4); + pixel + } + + pub(crate) fn new(world_pointer: *mut c_void, chunk_map_pointer: *mut c_void) -> Self { + Self { + world_pointer, + chunk_map_this: chunk_map_pointer, + } } } diff --git a/quant.ew/files/system/ewext_init/ewext_init.lua b/quant.ew/files/system/ewext_init/ewext_init.lua new file mode 100644 index 00000000..b5bad2d8 --- /dev/null +++ b/quant.ew/files/system/ewext_init/ewext_init.lua @@ -0,0 +1,14 @@ +local ffi = require("ffi") + +local module = {} + +function module.on_world_initialized() + local world_ffi = require("noitapatcher.nsew.world_ffi") + local grid_world = world_ffi.get_grid_world() + local chunk_map = grid_world.vtable.get_chunk_map(grid_world) + grid_world = tonumber(ffi.cast("intptr_t", grid_world)) + chunk_map = tonumber(ffi.cast("intptr_t", chunk_map)) + ewext.init_particle_world_state(grid_world, chunk_map) +end + +return module \ No newline at end of file diff --git a/quant.ew/init.lua b/quant.ew/init.lua index 542ebe3f..5fb83fd2 100755 --- a/quant.ew/init.lua +++ b/quant.ew/init.lua @@ -5,9 +5,6 @@ package.cpath = package.cpath .. ";./mods/quant.ew/?.dll" package.path = package.path .. ";./mods/quant.ew/?.lua" print(package.cpath) --- ewext = require("ewext") --- ewext() - dofile_once( "data/scripts/lib/utilities.lua" ) dofile_once("mods/quant.ew/files/system/player/player_cosmetics.lua") @@ -17,6 +14,8 @@ np.EnableGameSimulatePausing(false) np.InstallDamageDetailsPatch() np.SilenceLogs("Warning - streaming didn\'t find any chunks it could stream away...\n") +ewext = require("ewext") + -- Make some stuff global, as it's way too annoying to import each time. ctx = dofile_once("mods/quant.ew/files/core/ctx.lua") player_fns = dofile_once("mods/quant.ew/files/core/player_fns.lua") @@ -42,6 +41,8 @@ np.CrossCallAdd("ew_per_peer_seed", function() end) local function load_modules() + ctx.load_system("ewext_init") + ctx.dofile_and_add_hooks("mods/quant.ew/files/system/item_sync.lua") ctx.dofile_and_add_hooks("mods/quant.ew/files/system/player_sync.lua")