mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-10-19 07:03:16 +00:00
Allow returning errors from ewext functions to lua.
This commit is contained in:
parent
134584dcf2
commit
c781187e57
5 changed files with 109 additions and 15 deletions
25
ewext/Cargo.lock
generated
25
ewext/Cargo.lock
generated
|
@ -40,14 +40,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ewext"
|
name = "ewext"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
|
"eyre",
|
||||||
"iced-x86",
|
"iced-x86",
|
||||||
"libloading",
|
"libloading",
|
||||||
"noita_api_macro",
|
"noita_api_macro",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "eyre"
|
||||||
|
version = "0.6.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
|
||||||
|
dependencies = [
|
||||||
|
"indenter",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.31.1"
|
version = "0.31.1"
|
||||||
|
@ -69,6 +80,12 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indenter"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
|
@ -132,6 +149,12 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.89"
|
version = "1.0.89"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ewext"
|
name = "ewext"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
@ -16,3 +16,4 @@ libloading = "0.8.5"
|
||||||
backtrace = "0.3.74"
|
backtrace = "0.3.74"
|
||||||
iced-x86 = "1.21.0"
|
iced-x86 = "1.21.0"
|
||||||
noita_api_macro = {path = "noita_api_macro"}
|
noita_api_macro = {path = "noita_api_macro"}
|
||||||
|
eyre = "0.6.12"
|
||||||
|
|
|
@ -107,7 +107,9 @@ pub fn add_lua_fn(item: TokenStream) -> TokenStream {
|
||||||
let fn_name_c = proc_macro2::Literal::c_string(CString::new(fn_name).unwrap().as_c_str());
|
let fn_name_c = proc_macro2::Literal::c_string(CString::new(fn_name).unwrap().as_c_str());
|
||||||
quote! {
|
quote! {
|
||||||
unsafe extern "C" fn #bridge_fn_name(lua: *mut lua_State) -> c_int {
|
unsafe extern "C" fn #bridge_fn_name(lua: *mut lua_State) -> c_int {
|
||||||
#fn_name_ident(LuaState::new(lua)) as c_int
|
let lua_state = LuaState::new(lua);
|
||||||
|
lua_state.make_current();
|
||||||
|
crate::lua_state::LuaFnRet::do_return(#fn_name_ident(lua_state), lua_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
LUA.lua_pushcclosure(lua, Some(#bridge_fn_name), 0);
|
LUA.lua_pushcclosure(lua, Some(#bridge_fn_name), 0);
|
||||||
|
|
|
@ -6,8 +6,9 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use addr_grabber::{grab_addrs, grabbed_fns, grabbed_globals};
|
use addr_grabber::{grab_addrs, grabbed_fns, grabbed_globals};
|
||||||
|
use eyre::bail;
|
||||||
use lua_bindings::{lua_State, Lua51};
|
use lua_bindings::{lua_State, Lua51};
|
||||||
use lua_state::LuaState;
|
use lua_state::{LuaState, ValuesOnStack};
|
||||||
use noita::{ntypes::Entity, NoitaPixelRun, ParticleWorldState};
|
use noita::{ntypes::Entity, NoitaPixelRun, ParticleWorldState};
|
||||||
use noita_api_macro::add_lua_fn;
|
use noita_api_macro::add_lua_fn;
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ struct ExtState {
|
||||||
particle_world_state: Option<ParticleWorldState>,
|
particle_world_state: Option<ParticleWorldState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_particle_world_state(lua: LuaState) -> c_int {
|
fn init_particle_world_state(lua: LuaState) {
|
||||||
println!("\nInitializing particle world state");
|
println!("\nInitializing particle world state");
|
||||||
let world_pointer = lua.to_integer(1);
|
let world_pointer = lua.to_integer(1);
|
||||||
let chunk_map_pointer = lua.to_integer(2);
|
let chunk_map_pointer = lua.to_integer(2);
|
||||||
|
@ -50,10 +51,9 @@ fn init_particle_world_state(lua: LuaState) -> c_int {
|
||||||
runner: Default::default(),
|
runner: Default::default(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_area(lua: LuaState) -> c_int {
|
fn encode_area(lua: LuaState) -> ValuesOnStack {
|
||||||
let lua = lua.raw();
|
let lua = lua.raw();
|
||||||
let start_x = unsafe { LUA.lua_tointeger(lua, 1) } as i32;
|
let start_x = unsafe { LUA.lua_tointeger(lua, 1) } as i32;
|
||||||
let start_y = unsafe { LUA.lua_tointeger(lua, 2) } as i32;
|
let start_y = unsafe { LUA.lua_tointeger(lua, 2) } as i32;
|
||||||
|
@ -67,10 +67,10 @@ fn encode_area(lua: LuaState) -> c_int {
|
||||||
let runs = unsafe { pws.encode_area(start_x, start_y, end_x, end_y, encoded_buffer) };
|
let runs = unsafe { pws.encode_area(start_x, start_y, end_x, end_y, encoded_buffer) };
|
||||||
unsafe { LUA.lua_pushinteger(lua, runs as isize) };
|
unsafe { LUA.lua_pushinteger(lua, runs as isize) };
|
||||||
});
|
});
|
||||||
1
|
lua_state::ValuesOnStack(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_ephemerial(lua: LuaState) -> c_int {
|
fn make_ephemerial(lua: LuaState) -> eyre::Result<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let entity_id = lua.to_integer(1) as u32;
|
let entity_id = lua.to_integer(1) as u32;
|
||||||
|
|
||||||
|
@ -87,16 +87,16 @@ fn make_ephemerial(lua: LuaState) -> c_int {
|
||||||
out("ecx") _,
|
out("ecx") _,
|
||||||
out("eax") entity,
|
out("eax") entity,
|
||||||
);
|
);
|
||||||
if !entity.is_null() {
|
if entity.is_null() {
|
||||||
entity.cast::<c_void>().offset(0x8).cast::<u32>().write(0);
|
bail!("Entity {} not found", entity_id);
|
||||||
}
|
}
|
||||||
|
entity.cast::<c_void>().offset(0x8).cast::<u32>().write(0);
|
||||||
}
|
}
|
||||||
0
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_world_initialized(lua: LuaState) -> i32 {
|
fn on_world_initialized(lua: LuaState) {
|
||||||
grab_addrs(lua);
|
grab_addrs(lua);
|
||||||
0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
|
|
@ -1,10 +1,20 @@
|
||||||
use std::ffi::CStr;
|
use std::{
|
||||||
|
cell::Cell,
|
||||||
|
ffi::{c_char, c_int, CStr},
|
||||||
|
mem,
|
||||||
|
};
|
||||||
|
|
||||||
|
use eyre::OptionExt;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
lua_bindings::{lua_CFunction, lua_State, LUA_GLOBALSINDEX},
|
lua_bindings::{lua_CFunction, lua_State, LUA_GLOBALSINDEX},
|
||||||
LUA,
|
LUA,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static CURRENT_LUA_STATE: Cell<Option<LuaState>> = Cell::default();
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub(crate) struct LuaState {
|
pub(crate) struct LuaState {
|
||||||
lua: *mut lua_State,
|
lua: *mut lua_State,
|
||||||
|
@ -15,6 +25,17 @@ impl LuaState {
|
||||||
Self { lua }
|
Self { lua }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a lua state that is considered "current". Usually set when we get called from noita.
|
||||||
|
pub(crate) fn current() -> eyre::Result<Self> {
|
||||||
|
CURRENT_LUA_STATE
|
||||||
|
.get()
|
||||||
|
.ok_or_eyre("No current lua state available")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn make_current(self) {
|
||||||
|
CURRENT_LUA_STATE.set(Some(self));
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn raw(&self) -> *mut lua_State {
|
pub(crate) fn raw(&self) -> *mut lua_State {
|
||||||
self.lua
|
self.lua
|
||||||
}
|
}
|
||||||
|
@ -27,6 +48,12 @@ impl LuaState {
|
||||||
unsafe { LUA.lua_tocfunction(self.lua, index) }
|
unsafe { LUA.lua_tocfunction(self.lua, index) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn push_string(&self, s: &str) {
|
||||||
|
unsafe {
|
||||||
|
LUA.lua_pushstring(self.lua, s.as_bytes().as_ptr() as *const c_char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn get_global(&self, name: &CStr) {
|
pub(crate) fn get_global(&self, name: &CStr) {
|
||||||
unsafe { LUA.lua_getfield(self.lua, LUA_GLOBALSINDEX, name.as_ptr()) };
|
unsafe { LUA.lua_getfield(self.lua, LUA_GLOBALSINDEX, name.as_ptr()) };
|
||||||
}
|
}
|
||||||
|
@ -34,4 +61,45 @@ impl LuaState {
|
||||||
pub(crate) fn pop_last(&self) {
|
pub(crate) fn pop_last(&self) {
|
||||||
unsafe { LUA.lua_settop(self.lua, -2) };
|
unsafe { LUA.lua_settop(self.lua, -2) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Raise an error with message `s`
|
||||||
|
///
|
||||||
|
/// This takes String so that it gets deallocated properly, as this functions doesn't return.
|
||||||
|
unsafe fn raise_error(&self, s: String) -> ! {
|
||||||
|
self.push_string(&s);
|
||||||
|
mem::drop(s);
|
||||||
|
unsafe { LUA.lua_error(self.lua) };
|
||||||
|
// lua_error does not return.
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait LuaFnRet {
|
||||||
|
fn do_return(self, lua: LuaState) -> c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Function intends to return several values that it has on stack.
|
||||||
|
pub(crate) struct ValuesOnStack(pub(crate) c_int);
|
||||||
|
|
||||||
|
impl LuaFnRet for ValuesOnStack {
|
||||||
|
fn do_return(self, _lua: LuaState) -> c_int {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LuaFnRet for () {
|
||||||
|
fn do_return(self, _lua: LuaState) -> c_int {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: LuaFnRet> LuaFnRet for eyre::Result<R> {
|
||||||
|
fn do_return(self, lua: LuaState) -> c_int {
|
||||||
|
match self {
|
||||||
|
Ok(ok) => ok.do_return(lua),
|
||||||
|
Err(err) => unsafe {
|
||||||
|
lua.raise_error(format!("Error in ewext call: {:?}", err));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue