From 61035d8b0c9a1f8ec8a9ffee58d67ad21adaba02 Mon Sep 17 00:00:00 2001 From: IQuant Date: Mon, 25 Nov 2024 20:21:36 +0300 Subject: [PATCH] Allow writing to components --- ewext/noita_api/src/lib.rs | 65 +++++++++++++------------------- ewext/noita_api/src/lua.rs | 55 +++++++++++++++++---------- ewext/noita_api_macro/src/lib.rs | 22 +++-------- ewext/src/lib.rs | 1 + 4 files changed, 68 insertions(+), 75 deletions(-) diff --git a/ewext/noita_api/src/lib.rs b/ewext/noita_api/src/lib.rs index 7b347f29..debb82cf 100644 --- a/ewext/noita_api/src/lib.rs +++ b/ewext/noita_api/src/lib.rs @@ -15,6 +15,8 @@ pub struct Color(pub u32); noita_api_macro::generate_components!(); pub mod raw { + use eyre::Ok; + use super::{Color, ComponentID, EntityID, Obj}; use crate::lua::LuaGetValue; use crate::lua::LuaPutValue; @@ -24,49 +26,34 @@ pub mod raw { noita_api_macro::generate_api!(); - fn component_get_value_base( - component: ComponentID, - field: &str, - expected_results: i32, - ) -> eyre::Result<()> { + pub(crate) fn component_get_value(component: ComponentID, field: &str) -> eyre::Result + where + T: LuaGetValue, + { let lua = LuaState::current()?; lua.get_global(c"ComponentGetValue2"); lua.push_integer(component.0.into()); lua.push_string(field); - lua.call(2, expected_results); + lua.call(2, T::size_on_stack()); + let ret = T::get(lua, -1); + lua.pop_last_n(T::size_on_stack()); + ret + } + + pub(crate) fn component_set_value( + component: ComponentID, + field: &str, + value: T, + ) -> eyre::Result<()> + where + T: LuaPutValue, + { + let lua = LuaState::current()?; + lua.get_global(c"ComponentSetValue2"); + lua.push_integer(component.0.into()); + lua.push_string(field); + value.put(lua); + lua.call(2 + T::size_on_stack(), 0); Ok(()) } - - pub(crate) fn component_get_value_number( - component: ComponentID, - field: &str, - ) -> eyre::Result { - 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 { - 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 { - component_get_value_base(component, field, 1)?; - let lua = LuaState::current()?; - let ret = lua.to_bool(1); - lua.pop_last(); - Ok(ret) - } } diff --git a/ewext/noita_api/src/lua.rs b/ewext/noita_api/src/lua.rs index d1e694db..bda6f994 100644 --- a/ewext/noita_api/src/lua.rs +++ b/ewext/noita_api/src/lua.rs @@ -161,6 +161,9 @@ pub(crate) trait LuaPutValue { fn is_non_empty(&self) -> bool { true } + fn size_on_stack() -> i32 { + 1 + } } impl LuaPutValue for i32 { @@ -181,6 +184,12 @@ impl LuaPutValue for u32 { } } +impl LuaPutValue for f32 { + fn put(&self, lua: LuaState) { + lua.push_number(*self as f64); + } +} + impl LuaPutValue for f64 { fn put(&self, lua: LuaState) { lua.push_number(*self); @@ -250,7 +259,7 @@ pub(crate) trait LuaGetValue { fn get(lua: LuaState, index: i32) -> eyre::Result where Self: Sized; - fn size() -> i32 { + fn size_on_stack() -> i32 { 1 } } @@ -342,11 +351,14 @@ impl LuaGetValue for (T0, T1) { where Self: Sized, { - Ok((T0::get(lua, index - T1::size())?, T1::get(lua, index)?)) + Ok(( + T0::get(lua, index - T1::size_on_stack())?, + T1::get(lua, index)?, + )) } - fn size() -> i32 { - T0::size() + T1::size() + fn size_on_stack() -> i32 { + T0::size_on_stack() + T1::size_on_stack() } } @@ -356,14 +368,14 @@ impl LuaGetValue for (T0, T1, Self: Sized, { Ok(( - T0::get(lua, index - T1::size() - T2::size())?, - T1::get(lua, index - T2::size())?, + T0::get(lua, index - T1::size_on_stack() - T2::size_on_stack())?, + T1::get(lua, index - T2::size_on_stack())?, T2::get(lua, index)?, )) } - fn size() -> i32 { - T0::size() + T1::size() + T2::size() + fn size_on_stack() -> i32 { + T0::size_on_stack() + T1::size_on_stack() + T2::size_on_stack() } } @@ -375,15 +387,18 @@ impl LuaGetV Self: Sized, { Ok(( - T0::get(lua, index - T1::size() - T2::size() - T3::size())?, - T1::get(lua, index - T2::size() - T3::size())?, - T2::get(lua, index - T3::size())?, + T0::get( + lua, + index - T1::size_on_stack() - T2::size_on_stack() - T3::size_on_stack(), + )?, + T1::get(lua, index - T2::size_on_stack() - T3::size_on_stack())?, + T2::get(lua, index - T3::size_on_stack())?, T3::get(lua, index)?, )) } - fn size() -> i32 { - T0::size() + T1::size() + T2::size() + T3::size() + fn size_on_stack() -> i32 { + T0::size_on_stack() + T1::size_on_stack() + T2::size_on_stack() + T3::size_on_stack() } } @@ -394,12 +409,12 @@ impl::get(lua, index - T4::size())?; + let prev = <(T0, T1, T2, T3)>::get(lua, index - T4::size_on_stack())?; Ok((prev.0, prev.1, prev.2, prev.3, T4::get(lua, index)?)) } - fn size() -> i32 { - <(T0, T1, T2, T3)>::size() + T4::size() + fn size_on_stack() -> i32 { + <(T0, T1, T2, T3)>::size_on_stack() + T4::size_on_stack() } } @@ -416,12 +431,12 @@ impl< where Self: Sized, { - let prev = <(T0, T1, T2, T3, T4)>::get(lua, index - T5::size())?; + let prev = <(T0, T1, T2, T3, T4)>::get(lua, index - T5::size_on_stack())?; Ok((prev.0, prev.1, prev.2, prev.3, prev.4, T5::get(lua, index)?)) } - fn size() -> i32 { - <(T0, T1, T2, T3, T4)>::size() + T5::size() + fn size_on_stack() -> i32 { + <(T0, T1, T2, T3, T4)>::size_on_stack() + T5::size_on_stack() } } @@ -442,7 +457,7 @@ impl LuaGetValue for (bool, bool, bool, f64, f64, f64, f64, f64, f64, f64, f64) )) } - fn size() -> i32 { + fn size_on_stack() -> i32 { 11 } } diff --git a/ewext/noita_api_macro/src/lib.rs b/ewext/noita_api_macro/src/lib.rs index d0e9cd75..360cdadf 100644 --- a/ewext/noita_api_macro/src/lib.rs +++ b/ewext/noita_api_macro/src/lib.rs @@ -30,21 +30,10 @@ impl Typ { match self { Typ::Int => quote!(i32), Typ::UInt => quote!(u32), - Typ::Float => quote!(f64), + Typ::Float => quote!(f32), Typ::Double => quote!(f64), Typ::Bool => quote!(bool), - Typ::StdString => todo!(), - Typ::Vec2 => todo!(), - Typ::Other => todo!(), - } - } - - fn as_lua_type(&self) -> &'static str { - match self { - Typ::Int | Typ::UInt => "integer", - Typ::Float | Typ::Double => "number", - Typ::Bool => "bool", - Typ::StdString => todo!(), + Typ::StdString => quote!(Cow<'_, str>), Typ::Vec2 => todo!(), Typ::Other => todo!(), } @@ -159,15 +148,16 @@ fn generate_code_for_component(com: Component) -> proc_macro2::TokenStream { match field.typ { Typ::Int | Typ::UInt | Typ::Float | Typ::Double | Typ::Bool => { let field_type = field.typ.as_rust_type(); - let getter_fn = format_ident!("component_get_value_{}", field.typ.as_lua_type()); Some(quote! { #[doc = #field_doc] pub fn #field_name(self) -> eyre::Result<#field_type> { // This trasmute is used to reinterpret i32 as u32 in one case. - unsafe { std::mem::transmute(raw::#getter_fn(self.0, #field_name_s)) } + raw::component_get_value(self.0, #field_name_s) } #[doc = #field_doc] - pub fn #set_method_name(self, value: #field_type) -> eyre::Result<()> { todo!() } + pub fn #set_method_name(self, value: #field_type) -> eyre::Result<()> { + raw::component_set_value(self.0, #field_name_s, value) + } }) } _ => None, diff --git a/ewext/src/lib.rs b/ewext/src/lib.rs index c4491976..7ee97e73 100644 --- a/ewext/src/lib.rs +++ b/ewext/src/lib.rs @@ -121,6 +121,7 @@ fn test_fn(_lua: LuaState) -> eyre::Result<()> { .ok_or_eyre("Could not find damage model")?, ); let hp = damage_model.hp()?; + damage_model.set_hp(hp - 1.0)?; let transform = noita_api::raw::entity_get_transform(player)?;