mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-10-19 07:03:16 +00:00
Split noita api stuff into it's own crate
This commit is contained in:
parent
bac266e456
commit
66a5a009e2
11 changed files with 121 additions and 106 deletions
10
ewext/Cargo.lock
generated
10
ewext/Cargo.lock
generated
|
@ -46,6 +46,7 @@ dependencies = [
|
||||||
"eyre",
|
"eyre",
|
||||||
"iced-x86",
|
"iced-x86",
|
||||||
"libloading",
|
"libloading",
|
||||||
|
"noita_api",
|
||||||
"noita_api_macro",
|
"noita_api_macro",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -129,6 +130,15 @@ dependencies = [
|
||||||
"adler2",
|
"adler2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "noita_api"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"eyre",
|
||||||
|
"libloading",
|
||||||
|
"noita_api_macro",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "noita_api_macro"
|
name = "noita_api_macro"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
@ -17,3 +17,4 @@ 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"
|
eyre = "0.6.12"
|
||||||
|
noita_api = {path = "noita_api"}
|
9
ewext/noita_api/Cargo.toml
Normal file
9
ewext/noita_api/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "noita_api"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
eyre = "0.6.12"
|
||||||
|
libloading = "0.8.5"
|
||||||
|
noita_api_macro = {path = "../noita_api_macro"}
|
68
ewext/noita_api/src/lib.rs
Normal file
68
ewext/noita_api/src/lib.rs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
pub mod lua;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct EntityID(pub isize);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct ComponentID(pub isize);
|
||||||
|
|
||||||
|
pub struct Obj(pub usize);
|
||||||
|
|
||||||
|
pub struct Color(pub u32);
|
||||||
|
|
||||||
|
noita_api_macro::generate_components!();
|
||||||
|
|
||||||
|
pub mod raw {
|
||||||
|
use super::{Color, ComponentID, EntityID, Obj};
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use crate::lua::LuaState;
|
||||||
|
|
||||||
|
noita_api_macro::generate_api!();
|
||||||
|
|
||||||
|
fn component_get_value_base(
|
||||||
|
component: ComponentID,
|
||||||
|
field: &str,
|
||||||
|
expected_results: i32,
|
||||||
|
) -> eyre::Result<()> {
|
||||||
|
let lua = LuaState::current()?;
|
||||||
|
lua.get_global(c"ComponentGetValue2");
|
||||||
|
lua.push_integer(component.0);
|
||||||
|
lua.push_string(field);
|
||||||
|
lua.call(2, expected_results);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn component_get_value_number(
|
||||||
|
component: ComponentID,
|
||||||
|
field: &str,
|
||||||
|
) -> eyre::Result<f64> {
|
||||||
|
component_get_value_base(component, field, 1)?;
|
||||||
|
let lua = LuaState::current()?;
|
||||||
|
let ret = lua.to_number(1);
|
||||||
|
lua.pop_last();
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn component_get_value_integer(
|
||||||
|
component: ComponentID,
|
||||||
|
field: &str,
|
||||||
|
) -> eyre::Result<i32> {
|
||||||
|
component_get_value_base(component, field, 1)?;
|
||||||
|
let lua = LuaState::current()?;
|
||||||
|
let ret = lua.to_integer(1);
|
||||||
|
lua.pop_last();
|
||||||
|
Ok(ret as i32)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn component_get_value_bool(
|
||||||
|
component: ComponentID,
|
||||||
|
field: &str,
|
||||||
|
) -> eyre::Result<bool> {
|
||||||
|
component_get_value_base(component, field, 1)?;
|
||||||
|
let lua = LuaState::current()?;
|
||||||
|
let ret = lua.to_bool(1);
|
||||||
|
lua.pop_last();
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,24 @@
|
||||||
|
pub mod lua_bindings;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
ffi::{c_char, c_int, CStr},
|
ffi::{c_char, c_int, CStr},
|
||||||
mem, slice,
|
mem, slice,
|
||||||
|
sync::LazyLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
use eyre::{bail, Context, OptionExt};
|
use eyre::{bail, Context, OptionExt};
|
||||||
|
use lua_bindings::{lua_CFunction, lua_State, Lua51, LUA_GLOBALSINDEX};
|
||||||
use crate::{
|
|
||||||
lua_bindings::{lua_CFunction, lua_State, LUA_GLOBALSINDEX},
|
|
||||||
LUA,
|
|
||||||
};
|
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static CURRENT_LUA_STATE: Cell<Option<LuaState>> = Cell::default();
|
static CURRENT_LUA_STATE: Cell<Option<LuaState>> = Cell::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub static LUA: LazyLock<Lua51> = LazyLock::new(|| unsafe {
|
||||||
|
let lib = libloading::Library::new("./lua51.dll").expect("library to exist");
|
||||||
|
Lua51::from_library(lib).expect("library to be lua")
|
||||||
|
});
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct LuaState {
|
pub struct LuaState {
|
||||||
lua: *mut lua_State,
|
lua: *mut lua_State,
|
||||||
|
@ -36,7 +40,7 @@ impl LuaState {
|
||||||
CURRENT_LUA_STATE.set(Some(self));
|
CURRENT_LUA_STATE.set(Some(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn raw(&self) -> *mut lua_State {
|
pub fn raw(&self) -> *mut lua_State {
|
||||||
self.lua
|
self.lua
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,12 +121,12 @@ impl LuaState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait LuaFnRet {
|
pub trait LuaFnRet {
|
||||||
fn do_return(self, lua: LuaState) -> c_int;
|
fn do_return(self, lua: LuaState) -> c_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function intends to return several values that it has on stack.
|
/// Function intends to return several values that it has on stack.
|
||||||
pub(crate) struct ValuesOnStack(pub(crate) c_int);
|
pub struct ValuesOnStack(pub c_int);
|
||||||
|
|
||||||
impl LuaFnRet for ValuesOnStack {
|
impl LuaFnRet for ValuesOnStack {
|
||||||
fn do_return(self, _lua: LuaState) -> c_int {
|
fn do_return(self, _lua: LuaState) -> c_int {
|
||||||
|
@ -141,7 +145,7 @@ impl<R: LuaFnRet> LuaFnRet for eyre::Result<R> {
|
||||||
match self {
|
match self {
|
||||||
Ok(ok) => ok.do_return(lua),
|
Ok(ok) => ok.do_return(lua),
|
||||||
Err(err) => unsafe {
|
Err(err) => unsafe {
|
||||||
lua.raise_error(format!("Error in ewext call: {:?}", err));
|
lua.raise_error(format!("Error in rust call: {:?}", err));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,7 @@
|
||||||
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
|
members = ["noita_api", "noita_api_macro"]
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "noita_api_macro"
|
name = "noita_api_macro"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
@ -201,7 +201,7 @@ fn generate_code_for_component(com: Component) -> proc_macro2::TokenStream {
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct #component_name(pub(crate) ComponentID);
|
pub struct #component_name(pub ComponentID);
|
||||||
|
|
||||||
impl #component_name {
|
impl #component_name {
|
||||||
#(#impls)*
|
#(#impls)*
|
||||||
|
@ -271,7 +271,7 @@ fn generate_code_for_api_fn(api_fn: ApiFn) -> proc_macro2::TokenStream {
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[doc = #fn_doc]
|
#[doc = #fn_doc]
|
||||||
pub(crate) fn #fn_name(#(#args,)*) -> eyre::Result<#ret_type> {
|
pub fn #fn_name(#(#args,)*) -> eyre::Result<#ret_type> {
|
||||||
let lua = LuaState::current()?;
|
let lua = LuaState::current()?;
|
||||||
|
|
||||||
lua.get_global(#fn_name_c);
|
lua.get_global(#fn_name_c);
|
||||||
|
@ -304,9 +304,9 @@ pub fn add_lua_fn(item: TokenStream) -> TokenStream {
|
||||||
let fn_name_c = name_to_c_literal(fn_name);
|
let fn_name_c = name_to_c_literal(fn_name);
|
||||||
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 {
|
||||||
let lua_state = LuaState::new(lua);
|
let lua_state = noita_api::lua::LuaState::new(lua);
|
||||||
lua_state.make_current();
|
lua_state.make_current();
|
||||||
crate::lua_state::LuaFnRet::do_return(#fn_name_ident(lua_state), lua_state)
|
noita_api::lua::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);
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
use std::{mem, os::raw::c_void, ptr, sync::OnceLock};
|
use std::{mem, os::raw::c_void, ptr, sync::OnceLock};
|
||||||
|
|
||||||
use iced_x86::{Decoder, DecoderOptions, Mnemonic};
|
use iced_x86::{Decoder, DecoderOptions, Mnemonic};
|
||||||
|
use noita_api::lua::LuaState;
|
||||||
|
|
||||||
use crate::{
|
use crate::noita::ntypes::{EntityManager, ThiscallFn};
|
||||||
lua_state::LuaState,
|
|
||||||
noita::ntypes::{EntityManager, ThiscallFn},
|
|
||||||
};
|
|
||||||
|
|
||||||
static GRABBED: OnceLock<Grabbed> = OnceLock::new();
|
static GRABBED: OnceLock<Grabbed> = OnceLock::new();
|
||||||
|
|
||||||
|
|
|
@ -1,31 +1,21 @@
|
||||||
use crate::noita::api::DamageModelComponent;
|
|
||||||
use std::{
|
use std::{
|
||||||
arch::asm,
|
arch::asm,
|
||||||
cell::{LazyCell, RefCell},
|
cell::{LazyCell, RefCell},
|
||||||
ffi::{c_int, c_void},
|
ffi::{c_int, c_void},
|
||||||
sync::LazyLock,
|
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
use addr_grabber::{grab_addrs, grabbed_fns, grabbed_globals};
|
use addr_grabber::{grab_addrs, grabbed_fns, grabbed_globals};
|
||||||
use eyre::bail;
|
use eyre::bail;
|
||||||
use lua_bindings::{lua_State, Lua51};
|
|
||||||
use lua_state::{LuaState, ValuesOnStack};
|
|
||||||
use noita::{ntypes::Entity, pixel::NoitaPixelRun, ParticleWorldState};
|
|
||||||
use noita_api_macro::add_lua_fn;
|
|
||||||
|
|
||||||
mod lua_bindings;
|
use noita::{ntypes::Entity, pixel::NoitaPixelRun, ParticleWorldState};
|
||||||
pub mod lua_state;
|
use noita_api::lua::{lua_bindings::lua_State, LuaState, ValuesOnStack, LUA};
|
||||||
|
use noita_api_macro::add_lua_fn;
|
||||||
|
|
||||||
pub mod noita;
|
pub mod noita;
|
||||||
|
|
||||||
mod addr_grabber;
|
mod addr_grabber;
|
||||||
|
|
||||||
static LUA: LazyLock<Lua51> = LazyLock::new(|| unsafe {
|
|
||||||
let lib = libloading::Library::new("./lua51.dll").expect("library to exist");
|
|
||||||
Lua51::from_library(lib).expect("library to be lua")
|
|
||||||
});
|
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static STATE: LazyCell<RefCell<ExtState>> = LazyCell::new(|| {
|
static STATE: LazyCell<RefCell<ExtState>> = LazyCell::new(|| {
|
||||||
println!("Initializing ExtState");
|
println!("Initializing ExtState");
|
||||||
|
@ -69,7 +59,7 @@ fn encode_area(lua: LuaState) -> ValuesOnStack {
|
||||||
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) };
|
||||||
});
|
});
|
||||||
lua_state::ValuesOnStack(1)
|
ValuesOnStack(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_ephemerial(lua: LuaState) -> eyre::Result<()> {
|
fn make_ephemerial(lua: LuaState) -> eyre::Result<()> {
|
||||||
|
@ -105,12 +95,12 @@ fn bench_fn(_lua: LuaState) -> eyre::Result<()> {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let iters = 10000;
|
let iters = 10000;
|
||||||
for _ in 0..iters {
|
for _ in 0..iters {
|
||||||
let player = noita::api::raw::entity_get_closest_with_tag(0.0, 0.0, "player_unit".into())?;
|
let player = noita_api::raw::entity_get_closest_with_tag(0.0, 0.0, "player_unit".into())?;
|
||||||
noita::api::raw::entity_set_transform(player, 0.0, Some(0.0), None, None, None)?;
|
noita_api::raw::entity_set_transform(player, 0.0, Some(0.0), None, None, None)?;
|
||||||
}
|
}
|
||||||
let elapsed = start.elapsed();
|
let elapsed = start.elapsed();
|
||||||
|
|
||||||
noita::api::raw::game_print(
|
noita_api::raw::game_print(
|
||||||
format!(
|
format!(
|
||||||
"Took {}us to test, {}ns per call",
|
"Took {}us to test, {}ns per call",
|
||||||
elapsed.as_micros(),
|
elapsed.as_micros(),
|
||||||
|
@ -123,15 +113,15 @@ fn bench_fn(_lua: LuaState) -> eyre::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_fn(_lua: LuaState) -> eyre::Result<()> {
|
fn test_fn(_lua: LuaState) -> eyre::Result<()> {
|
||||||
let player = noita::api::raw::entity_get_closest_with_tag(0.0, 0.0, "player_unit".into())?;
|
let player = noita_api::raw::entity_get_closest_with_tag(0.0, 0.0, "player_unit".into())?;
|
||||||
let damage_model = DamageModelComponent(noita::api::raw::entity_get_first_component(
|
let damage_model = noita_api::DamageModelComponent(noita_api::raw::entity_get_first_component(
|
||||||
player,
|
player,
|
||||||
"DamageModelComponent".into(),
|
"DamageModelComponent".into(),
|
||||||
None,
|
None,
|
||||||
)?);
|
)?);
|
||||||
let hp = damage_model.hp()?;
|
let hp = damage_model.hp()?;
|
||||||
|
|
||||||
noita::api::raw::game_print(
|
noita_api::raw::game_print(
|
||||||
format!("Component: {:?}, Hp: {}", damage_model.0, hp * 25.0).into(),
|
format!("Component: {:?}, Hp: {}", damage_model.0, hp * 25.0).into(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
|
@ -3,75 +3,6 @@ use std::{ffi::c_void, mem};
|
||||||
pub(crate) mod ntypes;
|
pub(crate) mod ntypes;
|
||||||
pub(crate) mod pixel;
|
pub(crate) mod pixel;
|
||||||
|
|
||||||
pub mod api {
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct EntityID(isize);
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct ComponentID(isize);
|
|
||||||
|
|
||||||
pub struct Obj(usize);
|
|
||||||
|
|
||||||
pub struct Color(u32);
|
|
||||||
|
|
||||||
noita_api_macro::generate_components!();
|
|
||||||
|
|
||||||
pub mod raw {
|
|
||||||
use super::{Color, ComponentID, EntityID, Obj};
|
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
use crate::LuaState;
|
|
||||||
|
|
||||||
noita_api_macro::generate_api!();
|
|
||||||
|
|
||||||
fn component_get_value_base(
|
|
||||||
component: ComponentID,
|
|
||||||
field: &str,
|
|
||||||
expected_results: i32,
|
|
||||||
) -> eyre::Result<()> {
|
|
||||||
let lua = LuaState::current()?;
|
|
||||||
lua.get_global(c"ComponentGetValue2");
|
|
||||||
lua.push_integer(component.0);
|
|
||||||
lua.push_string(field);
|
|
||||||
lua.call(2, expected_results);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn component_get_value_number(
|
|
||||||
component: ComponentID,
|
|
||||||
field: &str,
|
|
||||||
) -> eyre::Result<f64> {
|
|
||||||
component_get_value_base(component, field, 1)?;
|
|
||||||
let lua = LuaState::current()?;
|
|
||||||
let ret = lua.to_number(1);
|
|
||||||
lua.pop_last();
|
|
||||||
Ok(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn component_get_value_integer(
|
|
||||||
component: ComponentID,
|
|
||||||
field: &str,
|
|
||||||
) -> eyre::Result<i32> {
|
|
||||||
component_get_value_base(component, field, 1)?;
|
|
||||||
let lua = LuaState::current()?;
|
|
||||||
let ret = lua.to_integer(1);
|
|
||||||
lua.pop_last();
|
|
||||||
Ok(ret as i32)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn component_get_value_bool(
|
|
||||||
component: ComponentID,
|
|
||||||
field: &str,
|
|
||||||
) -> eyre::Result<bool> {
|
|
||||||
component_get_value_base(component, field, 1)?;
|
|
||||||
let lua = LuaState::current()?;
|
|
||||||
let ret = lua.to_bool(1);
|
|
||||||
lua.pop_last();
|
|
||||||
Ok(ret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct ParticleWorldState {
|
pub(crate) struct ParticleWorldState {
|
||||||
pub(crate) _world_ptr: *mut c_void,
|
pub(crate) _world_ptr: *mut c_void,
|
||||||
pub(crate) chunk_map_ptr: *mut c_void,
|
pub(crate) chunk_map_ptr: *mut c_void,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue