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]]
|
||||
name = "ewext"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"eyre",
|
||||
"iced-x86",
|
||||
"libloading",
|
||||
"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]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
|
@ -69,6 +80,12 @@ dependencies = [
|
|||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indenter"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
|
@ -132,6 +149,12 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.89"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ewext"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
@ -16,3 +16,4 @@ libloading = "0.8.5"
|
|||
backtrace = "0.3.74"
|
||||
iced-x86 = "1.21.0"
|
||||
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());
|
||||
quote! {
|
||||
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);
|
||||
|
|
|
@ -6,8 +6,9 @@ use std::{
|
|||
};
|
||||
|
||||
use addr_grabber::{grab_addrs, grabbed_fns, grabbed_globals};
|
||||
use eyre::bail;
|
||||
use lua_bindings::{lua_State, Lua51};
|
||||
use lua_state::LuaState;
|
||||
use lua_state::{LuaState, ValuesOnStack};
|
||||
use noita::{ntypes::Entity, NoitaPixelRun, ParticleWorldState};
|
||||
use noita_api_macro::add_lua_fn;
|
||||
|
||||
|
@ -35,7 +36,7 @@ struct ExtState {
|
|||
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");
|
||||
let world_pointer = lua.to_integer(1);
|
||||
let chunk_map_pointer = lua.to_integer(2);
|
||||
|
@ -50,10 +51,9 @@ fn init_particle_world_state(lua: LuaState) -> c_int {
|
|||
runner: Default::default(),
|
||||
});
|
||||
});
|
||||
0
|
||||
}
|
||||
|
||||
fn encode_area(lua: LuaState) -> c_int {
|
||||
fn encode_area(lua: LuaState) -> ValuesOnStack {
|
||||
let lua = lua.raw();
|
||||
let start_x = unsafe { LUA.lua_tointeger(lua, 1) } 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) };
|
||||
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 {
|
||||
let entity_id = lua.to_integer(1) as u32;
|
||||
|
||||
|
@ -87,16 +87,16 @@ fn make_ephemerial(lua: LuaState) -> c_int {
|
|||
out("ecx") _,
|
||||
out("eax") entity,
|
||||
);
|
||||
if !entity.is_null() {
|
||||
if entity.is_null() {
|
||||
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);
|
||||
0
|
||||
}
|
||||
|
||||
/// # 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::{
|
||||
lua_bindings::{lua_CFunction, lua_State, LUA_GLOBALSINDEX},
|
||||
LUA,
|
||||
};
|
||||
|
||||
thread_local! {
|
||||
static CURRENT_LUA_STATE: Cell<Option<LuaState>> = Cell::default();
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(crate) struct LuaState {
|
||||
lua: *mut lua_State,
|
||||
|
@ -15,6 +25,17 @@ impl LuaState {
|
|||
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 {
|
||||
self.lua
|
||||
}
|
||||
|
@ -27,6 +48,12 @@ impl LuaState {
|
|||
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) {
|
||||
unsafe { LUA.lua_getfield(self.lua, LUA_GLOBALSINDEX, name.as_ptr()) };
|
||||
}
|
||||
|
@ -34,4 +61,45 @@ impl LuaState {
|
|||
pub(crate) fn pop_last(&self) {
|
||||
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