Allow writing to components

This commit is contained in:
IQuant 2024-11-25 20:21:36 +03:00
parent 22aaa9fb18
commit 61035d8b0c
4 changed files with 68 additions and 75 deletions

View file

@ -15,6 +15,8 @@ pub struct Color(pub u32);
noita_api_macro::generate_components!(); noita_api_macro::generate_components!();
pub mod raw { pub mod raw {
use eyre::Ok;
use super::{Color, ComponentID, EntityID, Obj}; use super::{Color, ComponentID, EntityID, Obj};
use crate::lua::LuaGetValue; use crate::lua::LuaGetValue;
use crate::lua::LuaPutValue; use crate::lua::LuaPutValue;
@ -24,49 +26,34 @@ pub mod raw {
noita_api_macro::generate_api!(); noita_api_macro::generate_api!();
fn component_get_value_base( pub(crate) fn component_get_value<T>(component: ComponentID, field: &str) -> eyre::Result<T>
component: ComponentID, where
field: &str, T: LuaGetValue,
expected_results: i32, {
) -> eyre::Result<()> {
let lua = LuaState::current()?; let lua = LuaState::current()?;
lua.get_global(c"ComponentGetValue2"); lua.get_global(c"ComponentGetValue2");
lua.push_integer(component.0.into()); lua.push_integer(component.0.into());
lua.push_string(field); 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<T>(
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(()) 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)
}
} }

View file

@ -161,6 +161,9 @@ pub(crate) trait LuaPutValue {
fn is_non_empty(&self) -> bool { fn is_non_empty(&self) -> bool {
true true
} }
fn size_on_stack() -> i32 {
1
}
} }
impl LuaPutValue for i32 { 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 { impl LuaPutValue for f64 {
fn put(&self, lua: LuaState) { fn put(&self, lua: LuaState) {
lua.push_number(*self); lua.push_number(*self);
@ -250,7 +259,7 @@ pub(crate) trait LuaGetValue {
fn get(lua: LuaState, index: i32) -> eyre::Result<Self> fn get(lua: LuaState, index: i32) -> eyre::Result<Self>
where where
Self: Sized; Self: Sized;
fn size() -> i32 { fn size_on_stack() -> i32 {
1 1
} }
} }
@ -342,11 +351,14 @@ impl<T0: LuaGetValue, T1: LuaGetValue> LuaGetValue for (T0, T1) {
where where
Self: Sized, 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 { fn size_on_stack() -> i32 {
T0::size() + T1::size() T0::size_on_stack() + T1::size_on_stack()
} }
} }
@ -356,14 +368,14 @@ impl<T0: LuaGetValue, T1: LuaGetValue, T2: LuaGetValue> LuaGetValue for (T0, T1,
Self: Sized, Self: Sized,
{ {
Ok(( Ok((
T0::get(lua, index - T1::size() - T2::size())?, T0::get(lua, index - T1::size_on_stack() - T2::size_on_stack())?,
T1::get(lua, index - T2::size())?, T1::get(lua, index - T2::size_on_stack())?,
T2::get(lua, index)?, T2::get(lua, index)?,
)) ))
} }
fn size() -> i32 { fn size_on_stack() -> i32 {
T0::size() + T1::size() + T2::size() T0::size_on_stack() + T1::size_on_stack() + T2::size_on_stack()
} }
} }
@ -375,15 +387,18 @@ impl<T0: LuaGetValue, T1: LuaGetValue, T2: LuaGetValue, T3: LuaGetValue> LuaGetV
Self: Sized, Self: Sized,
{ {
Ok(( Ok((
T0::get(lua, index - T1::size() - T2::size() - T3::size())?, T0::get(
T1::get(lua, index - T2::size() - T3::size())?, lua,
T2::get(lua, index - T3::size())?, 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)?, T3::get(lua, index)?,
)) ))
} }
fn size() -> i32 { fn size_on_stack() -> i32 {
T0::size() + T1::size() + T2::size() + T3::size() T0::size_on_stack() + T1::size_on_stack() + T2::size_on_stack() + T3::size_on_stack()
} }
} }
@ -394,12 +409,12 @@ impl<T0: LuaGetValue, T1: LuaGetValue, T2: LuaGetValue, T3: LuaGetValue, T4: Lua
where where
Self: Sized, Self: Sized,
{ {
let prev = <(T0, T1, T2, T3)>::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)?)) Ok((prev.0, prev.1, prev.2, prev.3, T4::get(lua, index)?))
} }
fn size() -> i32 { fn size_on_stack() -> i32 {
<(T0, T1, T2, T3)>::size() + T4::size() <(T0, T1, T2, T3)>::size_on_stack() + T4::size_on_stack()
} }
} }
@ -416,12 +431,12 @@ impl<
where where
Self: Sized, 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)?)) Ok((prev.0, prev.1, prev.2, prev.3, prev.4, T5::get(lua, index)?))
} }
fn size() -> i32 { fn size_on_stack() -> i32 {
<(T0, T1, T2, T3, T4)>::size() + T5::size() <(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 11
} }
} }

View file

@ -30,21 +30,10 @@ impl Typ {
match self { match self {
Typ::Int => quote!(i32), Typ::Int => quote!(i32),
Typ::UInt => quote!(u32), Typ::UInt => quote!(u32),
Typ::Float => quote!(f64), Typ::Float => quote!(f32),
Typ::Double => quote!(f64), Typ::Double => quote!(f64),
Typ::Bool => quote!(bool), Typ::Bool => quote!(bool),
Typ::StdString => todo!(), Typ::StdString => quote!(Cow<'_, str>),
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::Vec2 => todo!(), Typ::Vec2 => todo!(),
Typ::Other => todo!(), Typ::Other => todo!(),
} }
@ -159,15 +148,16 @@ fn generate_code_for_component(com: Component) -> proc_macro2::TokenStream {
match field.typ { match field.typ {
Typ::Int | Typ::UInt | Typ::Float | Typ::Double | Typ::Bool => { Typ::Int | Typ::UInt | Typ::Float | Typ::Double | Typ::Bool => {
let field_type = field.typ.as_rust_type(); let field_type = field.typ.as_rust_type();
let getter_fn = format_ident!("component_get_value_{}", field.typ.as_lua_type());
Some(quote! { Some(quote! {
#[doc = #field_doc] #[doc = #field_doc]
pub fn #field_name(self) -> eyre::Result<#field_type> { pub fn #field_name(self) -> eyre::Result<#field_type> {
// This trasmute is used to reinterpret i32 as u32 in one case. // 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] #[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, _ => None,

View file

@ -121,6 +121,7 @@ fn test_fn(_lua: LuaState) -> eyre::Result<()> {
.ok_or_eyre("Could not find damage model")?, .ok_or_eyre("Could not find damage model")?,
); );
let hp = damage_model.hp()?; let hp = damage_model.hp()?;
damage_model.set_hp(hp - 1.0)?;
let transform = noita_api::raw::entity_get_transform(player)?; let transform = noita_api::raw::entity_get_transform(player)?;