1use yog_data::{Ref, Value};
23use yog_event::nanite::{Call, Get, Release, Resolve, Set};
24use yog_ids::{kind, nanite_ref};
25use yog_sync::{Arc, OnceLock};
26
27mod added;
28mod inject;
29mod java;
30pub use added::Added;
31pub use inject::{__declare, __yog_nanite_registry, __yog_nanites, Hook, InjectEntry};
32pub use java::{Java, Reply};
33
34#[doc(hidden)]
35pub use inject::subscribe as __subscribe;
36
37#[derive(Clone, Debug)]
39pub enum Handle {
40 Object(Arc<Held>),
41 Entity(String),
42}
43
44#[derive(Debug)]
46pub struct Held(u64);
47
48impl Drop for Held {
49 fn drop(&mut self) {
50 crate::call(&Release {
51 objects: vec![self.0],
52 });
53 }
54}
55
56impl Handle {
57 pub fn entity(uuid: impl Into<String>) -> Handle {
59 Handle::Entity(uuid.into())
60 }
61
62 pub fn to_value(&self) -> Value {
64 match self {
65 Handle::Object(held) => Value::Ref(Ref::new(nanite_ref::OBJECT, held.0.to_string())),
66 Handle::Entity(uuid) => Value::Ref(Ref::new(kind::ENTITY, uuid.clone())),
67 }
68 }
69
70 pub fn from_value(v: Value) -> Option<Handle> {
72 let Value::Ref(r) = v else { return None };
73 match r.kind.as_str() {
74 nanite_ref::OBJECT => r.id.parse().ok().map(|n| Handle::Object(Arc::new(Held(n)))),
75 kind::ENTITY => Some(Handle::Entity(r.id)),
76 _ => None,
77 }
78 }
79}
80
81pub trait Nanite: Sized {
84 const CLASS: &'static str;
86 fn from_handle(handle: Handle) -> Self;
87 fn handle(&self) -> &Handle;
88
89 fn of(entity: &yog_event::Entity) -> Self {
91 Self::from_handle(Handle::entity(entity.uuid.clone()))
92 }
93}
94
95pub struct Member {
97 class: &'static str,
98 name: &'static str,
99 desc: fn() -> String,
101 id: OnceLock<Option<u32>>,
102}
103
104pub const CONSTRUCTOR: &str = "<init>";
106
107impl Member {
108 pub const fn new(class: &'static str, name: &'static str, desc: fn() -> String) -> Member {
111 Member {
112 class,
113 name,
114 desc,
115 id: OnceLock::new(),
116 }
117 }
118
119 pub fn class(&self) -> &'static str {
121 self.class
122 }
123
124 pub fn signature(&self) -> (&'static str, String) {
126 (self.name, (self.desc)())
127 }
128
129 pub fn id(&self) -> Option<u32> {
131 *self.id.get_or_init(|| {
132 crate::call(&Resolve {
133 class: self.class.to_owned(),
134 name: self.name.to_owned(),
135 desc: (self.desc)(),
136 })
137 .flatten()
138 })
139 }
140
141 pub fn call(&self, target: Value, args: Vec<Value>) -> Option<Value> {
143 let member = self.id()?;
144 crate::call(&Call {
145 member,
146 target,
147 args,
148 })
149 .flatten()
150 }
151
152 pub fn get(&self, target: Value) -> Option<Value> {
154 let member = self.id()?;
155 crate::call(&Get { member, target }).flatten()
156 }
157
158 pub fn set(&self, target: Value, value: Value) -> bool {
160 let Some(member) = self.id() else {
161 return false;
162 };
163 crate::call(&Set {
164 member,
165 target,
166 value,
167 })
168 .unwrap_or(false)
169 }
170}
171
172pub fn method_desc(params: &[String], ret: &str) -> String {
174 format!("({}){ret}", params.concat())
175}
176
177#[cfg(test)]
178mod tests;