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
56yog_data::kind!(HeldObject = nanite_ref::OBJECT: u64);
57
58impl Handle {
59 pub fn entity(uuid: impl Into<String>) -> Handle {
61 Handle::Entity(uuid.into())
62 }
63
64 pub fn to_value(&self) -> Value {
66 match self {
67 Handle::Object(held) => Value::Ref(Ref::of::<HeldObject>(&held.0)),
68 Handle::Entity(uuid) => Value::Ref(Ref::of::<yog_data::kinds::Entity>(uuid)),
69 }
70 }
71
72 pub fn from_value(v: Value) -> Option<Handle> {
74 let Value::Ref(r) = v else { return None };
75 match r.kind.as_str() {
76 nanite_ref::OBJECT => {
77 r.id.as_str()
78 .parse()
79 .ok()
80 .map(|n| Handle::Object(Arc::new(Held(n))))
81 }
82 kind::ENTITY => Some(Handle::Entity(r.id.as_str().to_owned())),
83 _ => None,
84 }
85 }
86}
87
88pub trait Nanite: Sized {
91 const CLASS: &'static str;
93 fn from_handle(handle: Handle) -> Self;
94 fn handle(&self) -> &Handle;
95
96 fn of(entity: &yog_event::Entity) -> Self {
98 Self::from_handle(Handle::entity(entity.uuid.clone()))
99 }
100}
101
102pub struct Member {
104 class: &'static str,
105 name: &'static str,
106 desc: fn() -> String,
108 id: OnceLock<Option<u32>>,
109}
110
111pub const CONSTRUCTOR: &str = "<init>";
113
114impl Member {
115 pub const fn new(class: &'static str, name: &'static str, desc: fn() -> String) -> Member {
118 Member {
119 class,
120 name,
121 desc,
122 id: OnceLock::new(),
123 }
124 }
125
126 pub fn class(&self) -> &'static str {
128 self.class
129 }
130
131 pub fn signature(&self) -> (&'static str, String) {
133 (self.name, (self.desc)())
134 }
135
136 pub fn id(&self) -> Option<u32> {
138 *self.id.get_or_init(|| {
139 crate::call(&Resolve {
140 class: self.class.to_owned(),
141 name: self.name.to_owned(),
142 desc: (self.desc)(),
143 })
144 .flatten()
145 })
146 }
147
148 pub fn call(&self, target: Value, args: Vec<Value>) -> Option<Value> {
150 let member = self.id()?;
151 crate::call(&Call {
152 member,
153 target,
154 args,
155 })
156 .flatten()
157 }
158
159 pub fn get(&self, target: Value) -> Option<Value> {
161 let member = self.id()?;
162 crate::call(&Get { member, target }).flatten()
163 }
164
165 pub fn set(&self, target: Value, value: Value) -> bool {
167 let Some(member) = self.id() else {
168 return false;
169 };
170 crate::call(&Set {
171 member,
172 target,
173 value,
174 })
175 .unwrap_or(false)
176 }
177}
178
179pub fn method_desc(params: &[String], ret: &str) -> String {
181 format!("({}){ret}", params.concat())
182}
183
184#[cfg(test)]
185mod tests;