Uhh still can't delete WSC properly without crashing anything

This commit is contained in:
IQuant 2024-11-12 17:26:42 +03:00
parent f1a0bbf07f
commit c4e6fe2dd4
4 changed files with 82 additions and 9 deletions

2
ewext/Cargo.lock generated
View file

@ -40,7 +40,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "ewext" name = "ewext"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"iced-x86", "iced-x86",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "ewext" name = "ewext"
version = "0.1.0" version = "0.2.0"
edition = "2021" edition = "2021"
[lib] [lib]

View file

@ -20,18 +20,30 @@ static LUA: LazyLock<Lua51> = LazyLock::new(|| unsafe {
}); });
thread_local! { thread_local! {
static STATE: LazyCell<RefCell<ExtState>> = LazyCell::new(|| ExtState::default().into()); static STATE: LazyCell<RefCell<ExtState>> = LazyCell::new(|| {
println!("Initializing ExtState");
ExtState::default().into()
});
}
struct SavedWorldState {
game_global: usize,
world_state_entity: usize,
world_state_related: usize,
} }
struct GrabbedGlobals { struct GrabbedGlobals {
game_global: *const c_void, // These 3 actually point to a pointer.
world_state_entity: *const c_void, game_global: *mut usize,
world_state_entity: *mut usize,
world_state_related: *mut usize,
} }
#[derive(Default)] #[derive(Default)]
struct ExtState { struct ExtState {
particle_world_state: Option<ParticleWorldState>, particle_world_state: Option<ParticleWorldState>,
globals: Option<GrabbedGlobals>, globals: Option<GrabbedGlobals>,
saved_world_state: Option<SavedWorldState>,
} }
// const EWEXT: [(&'static str, Function); 1] = [("testfn", None)]; // const EWEXT: [(&'static str, Function); 1] = [("testfn", None)];
@ -70,11 +82,56 @@ unsafe extern "C" fn encode_area(lua: *mut lua_State) -> c_int {
1 1
} }
unsafe fn save_world_state() {
STATE.with(|state| {
let mut state = state.borrow_mut();
let game_global = state.globals.as_ref().unwrap().game_global.read();
let world_state_entity = state.globals.as_ref().unwrap().world_state_entity.read();
let world_state_related = state.globals.as_ref().unwrap().world_state_related.read();
state.saved_world_state = Some(SavedWorldState {
game_global,
world_state_entity,
world_state_related,
})
});
}
unsafe fn load_world_state() {
println!("Loading world state");
STATE.with(|state| {
let state = state.borrow_mut();
let saved_ws = state.saved_world_state.as_ref().unwrap();
let globals = state.globals.as_ref().unwrap();
globals.game_global.write(saved_ws.game_global);
globals
.world_state_entity
.write(saved_ws.world_state_entity);
globals
.world_state_related
.write(saved_ws.world_state_related);
});
}
unsafe extern "C" fn save_world_state_lua(lua: *mut lua_State) -> i32 {
if STATE.with(|state| state.borrow().globals.is_none()) {
grab_addrs(lua);
}
save_world_state();
0
}
unsafe extern "C" fn load_world_state_lua(_lua: *mut lua_State) -> i32 {
load_world_state();
0
}
unsafe fn grab_addrs(lua: *mut lua_State) { unsafe fn grab_addrs(lua: *mut lua_State) {
LUA.lua_getfield(lua, LUA_GLOBALSINDEX, c"GameGetWorldStateEntity".as_ptr()); LUA.lua_getfield(lua, LUA_GLOBALSINDEX, c"GameGetWorldStateEntity".as_ptr());
let base = LUA.lua_tocfunction(lua, -1).unwrap() as *const c_void; let base = LUA.lua_tocfunction(lua, -1).unwrap() as *const c_void;
let world_state_entity = let world_state_entity =
addr_grabber::grab_addr_from_instruction(base, 0x007aa7ce - 0x007aa540, Mnemonic::Mov); addr_grabber::grab_addr_from_instruction(base, 0x007aa7ce - 0x007aa540, Mnemonic::Mov)
.cast();
println!( println!(
"World state entity addr: 0x{:x}", "World state entity addr: 0x{:x}",
world_state_entity as usize world_state_entity as usize
@ -91,7 +148,8 @@ unsafe fn grab_addrs(lua: *mut lua_State) {
load_game_global, load_game_global,
0x00439c17 - 0x00439bb0, 0x00439c17 - 0x00439bb0,
Mnemonic::Mov, Mnemonic::Mov,
); )
.cast();
println!("Game global addr: 0x{:x}", game_global as usize); println!("Game global addr: 0x{:x}", game_global as usize);
// Pop the last element. // Pop the last element.
LUA.lua_settop(lua, -2); LUA.lua_settop(lua, -2);
@ -100,6 +158,7 @@ unsafe fn grab_addrs(lua: *mut lua_State) {
state.borrow_mut().globals = Some(GrabbedGlobals { state.borrow_mut().globals = Some(GrabbedGlobals {
game_global, game_global,
world_state_entity, world_state_entity,
world_state_related: (0x01202ff0 as *mut usize),
}); });
}); });
} }
@ -111,14 +170,16 @@ unsafe fn grab_addrs(lua: *mut lua_State) {
pub unsafe extern "C" fn luaopen_ewext0(lua: *mut lua_State) -> c_int { pub unsafe extern "C" fn luaopen_ewext0(lua: *mut lua_State) -> c_int {
println!("Initializing ewext"); println!("Initializing ewext");
unsafe { unsafe {
grab_addrs(lua);
LUA.lua_createtable(lua, 0, 0); LUA.lua_createtable(lua, 0, 0);
LUA.lua_pushcclosure(lua, Some(init_particle_world_state), 0); LUA.lua_pushcclosure(lua, Some(init_particle_world_state), 0);
LUA.lua_setfield(lua, -2, c"init_particle_world_state".as_ptr()); LUA.lua_setfield(lua, -2, c"init_particle_world_state".as_ptr());
LUA.lua_pushcclosure(lua, Some(encode_area), 0); LUA.lua_pushcclosure(lua, Some(encode_area), 0);
LUA.lua_setfield(lua, -2, c"encode_area".as_ptr()); LUA.lua_setfield(lua, -2, c"encode_area".as_ptr());
LUA.lua_pushcclosure(lua, Some(load_world_state_lua), 0);
LUA.lua_setfield(lua, -2, c"load_world_state".as_ptr());
LUA.lua_pushcclosure(lua, Some(save_world_state_lua), 0);
LUA.lua_setfield(lua, -2, c"save_world_state".as_ptr());
} }
println!("Initializing ewext - Ok"); println!("Initializing ewext - Ok");
1 1

View file

@ -1,9 +1,13 @@
local ffi = require("ffi") local ffi = require("ffi")
local world_ffi = require("noitapatcher.nsew.world_ffi") local world_ffi = require("noitapatcher.nsew.world_ffi")
local initial_world_state_entity = nil
local module = {} local module = {}
function module.on_world_initialized() function module.on_world_initialized()
initial_world_state_entity = GameGetWorldStateEntity()
ewext.save_world_state()
local grid_world = world_ffi.get_grid_world() local grid_world = world_ffi.get_grid_world()
local chunk_map = grid_world.vtable.get_chunk_map(grid_world) local chunk_map = grid_world.vtable.get_chunk_map(grid_world)
grid_world = tonumber(ffi.cast("intptr_t", grid_world)) grid_world = tonumber(ffi.cast("intptr_t", grid_world))
@ -16,4 +20,12 @@ function module.on_local_player_spawn()
end end
function module.on_world_update()
if GameGetWorldStateEntity() ~= initial_world_state_entity then
GamePrint("Whoops WSE is different "..GameGetWorldStateEntity().." "..initial_world_state_entity)
-- EntityKill(GameGetWorldStateEntity())
ewext.load_world_state()
end
end
return module return module