Skip to content

Commit 7409fc8

Browse files
committed
🚀 😉 Next update, Day 2
1 parent 567498e commit 7409fc8

File tree

8 files changed

+378
-128
lines changed

8 files changed

+378
-128
lines changed

flake.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
];
4545

4646
LD_LIBRARY_PATH = "${pkgs.addDriverRunpath.driverLink}/lib:${pkgs.lib.makeLibraryPath libraries}";
47+
48+
RUST_BACKTRACE = "1";
4749
};
4850
};
4951
}

rust/src/java.rs

Lines changed: 74 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,83 @@
1+
mod macros;
2+
pub mod primitives;
3+
14
use jni::{
2-
objects::{JObject, JString},
5+
objects::{JObject, JValueOwned},
36
JNIEnv,
47
};
58

6-
pub const JAVA_STRING: &str = "java/lang/String";
9+
pub use macros::*;
10+
use primitives::Function;
711

8-
pub struct Identifier;
12+
pub trait IntoJValue {
13+
fn into_jvalue<'local>(self, env: &mut JNIEnv<'local>) -> JValueOwned<'local>;
14+
}
915

10-
impl Identifier {
11-
pub const MINECRAFT_IDENTIFIER: &str = "net/minecraft/util/Identifier";
12-
pub const MINECRAFT_IDENTIFIER_OF: &str =
13-
"(Ljava/lang/String;Ljava/lang/String;)Lnet/minecraft/util/Identifier;";
16+
impl IntoJValue for String {
17+
fn into_jvalue<'local>(self, env: &mut JNIEnv<'local>) -> JValueOwned<'local> {
18+
env.new_string(self).unwrap().into()
19+
}
20+
}
1421

15-
pub fn of<'local>(
16-
env: &mut JNIEnv<'local>,
17-
mod_id: JString<'local>,
18-
id: JString<'local>,
19-
) -> JObject<'local> {
20-
let identifier_class = env
21-
.find_class(Identifier::MINECRAFT_IDENTIFIER)
22-
.expect("Cannot get Identifier class");
23-
24-
env.call_static_method(
25-
identifier_class,
26-
"of",
27-
Identifier::MINECRAFT_IDENTIFIER_OF,
28-
&[(&mod_id).into(), (&id).into()],
29-
)
30-
.expect("Cannot generate Identifier")
31-
.l()
32-
.expect("Cannot convert to JObject")
22+
impl IntoJValue for JObject<'_> {
23+
fn into_jvalue<'local>(self, env: &mut JNIEnv<'local>) -> JValueOwned<'local> {
24+
env.new_local_ref(self).unwrap().into()
3325
}
3426
}
3527

36-
pub struct Items;
28+
pub trait JSignature {
29+
fn sig() -> String;
3730

38-
impl Items {
39-
pub const MINECRAFT_ITEM: &str = "net/minecraft/item/Item";
40-
pub const MINECRAFT_ITEMS: &str = "net/minecraft/item/Items";
41-
pub const MINECRAFT_ITEMS_REGISTER: &str =
42-
"(Lnet/minecraft/registry/RegistryKey;Ljava/util/function/Function;Lnet/minecraft/item/Item$Settings;)Lnet/minecraft/item/Item;";
31+
fn sig_type() -> String {
32+
let sig = Self::sig();
33+
let mut out = String::with_capacity(sig.len() + 2);
4334

44-
pub fn register<'local>(
45-
env: &mut JNIEnv<'local>,
46-
key: JObject<'local>,
47-
settings: JObject<'local>,
48-
) -> JObject<'local> {
49-
let items_class = env
50-
.find_class(Items::MINECRAFT_ITEMS)
51-
.expect("Cannot get Items class");
35+
out.push('L');
36+
out.push_str(&sig);
37+
out.push(';');
38+
39+
out
40+
}
41+
}
42+
43+
new_class!{RustBridge: "com/apika_probe_1/RustBridge" {
44+
static registerGroupEvent fn register_group_event(event: Event, item: Item);
45+
}}
46+
47+
new_class! {Event: "net/fabricmc/fabric/api/event/Event" {}}
48+
49+
impl Event<'_> {
50+
pub fn register<'local>(self, env: &mut JNIEnv<'local>, item: Item) {
51+
RustBridge::register_group_event(env, self, item)
52+
}
53+
}
54+
55+
new_class! {Identifier: "net/minecraft/util/Identifier" {
56+
static fn of(mod_id: String, id: String) -> Identifier<'local>;
57+
}}
58+
59+
new_class! {Item: "net/minecraft/item/Item" {}}
60+
61+
new_enum! {ItemGroups [RegistryKey]: "net/minecraft/item/ItemGroups" {
62+
REDSTONE
63+
}}
64+
65+
new_class! {ItemGroupEvents: "net/fabricmc/fabric/api/itemgroup/v1/ItemGroupEvents" {
66+
static modifyEntriesEvent fn modify_entries_event(registry_key: ItemGroups) -> Event<'local>;
67+
}}
68+
69+
new_class! {ItemSettings: "net/minecraft/item/Item$Settings" {}}
5270

53-
let item_class = env
54-
.find_class(Items::MINECRAFT_ITEM)
55-
.expect("Cannot get Item class");
71+
new_class! {Items: "net/minecraft/item/Items" {
72+
static register fn register_raw(key: RegistryKey<'local>, factory: Function<'local>, settings: ItemSettings<'local>) -> Item<'local>;
73+
}}
5674

75+
impl Items<'_> {
76+
pub fn register<'local>(
77+
env: &mut JNIEnv<'local>,
78+
key: RegistryKey<'local>,
79+
settings: ItemSettings<'local>,
80+
) -> Item<'local> {
5781
let factory = {
5882
let class = env.find_class("com/apika_probe_1/RustBridge").unwrap();
5983

@@ -63,62 +87,16 @@ impl Items {
6387
.unwrap()
6488
};
6589

66-
// let factory = env
67-
// // .get_static_field(&items_class, "new", "Ljava/util/function/Function;")
68-
// .get_static_field(&items_class, "new", "Lnet/minecraft/item/Item$Item;")
69-
// // .get_static_method_id(&items_class, "new", "(Lnet/minecraft/item/Item$Settings;)Lnet/minecraft/item/Item;")
70-
// .unwrap();
71-
72-
// let factory = unsafe {
73-
// let jni_interface = (*env.get_native_interface()).as_ref().unwrap();
74-
// // fn(_: *mut *const JNINativeInterface_, _: *mut _jobject, _: *mut _jmethodID, _: u8)
75-
// let to_reflected_method = jni_interface.ToReflectedMethod.unwrap();
76-
// let factory = to_reflected_method(
77-
// env.get_native_interface(),
78-
// **items_class,
79-
// factory.into_raw(),
80-
// 0,
81-
// );
82-
// JObject::from_raw(factory)
83-
// };
84-
85-
env.call_static_method(
86-
items_class,
87-
"register",
88-
Items::MINECRAFT_ITEMS_REGISTER,
89-
&[(&key).into(), (&factory).into(), (&settings).into()],
90-
)
91-
.expect("Cannot generate Item")
92-
.l()
93-
.expect("Cannot convert to JObject")
90+
Self::register_raw(env, key, factory.into(), settings)
9491
}
9592
}
9693

97-
pub struct RegistryKey;
98-
99-
impl RegistryKey {
100-
pub const MINECRAFT_REGISTRYKEY: &str = "net/minecraft/registry/RegistryKey";
101-
pub const MINECRAFT_REGISTRYKEYS: &str = "net/minecraft/registry/RegistryKeys";
94+
new_class! {ModifyEntries: "net/fabricmc/fabric/api/itemgroup/v1/ItemGroupEvents$ModifyEntries" {}}
10295

103-
pub const MINECRAFT_REGISTRYKEY_OF: &str = "(Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/util/Identifier;)Lnet/minecraft/registry/RegistryKey;";
96+
new_class! {RegistryKey: "net/minecraft/registry/RegistryKey" {
97+
static fn of(kind: RegistryKeys, id: Identifier<'local>) -> RegistryKey<'local>;
98+
}}
10499

105-
pub fn of<'local>(
106-
env: &mut JNIEnv<'local>,
107-
kind: JObject<'local>,
108-
id: JObject<'local>,
109-
) -> JObject<'local> {
110-
let registry_class = env
111-
.find_class(RegistryKey::MINECRAFT_REGISTRYKEY)
112-
.expect("Cannot get RegistryKey class");
113-
114-
env.call_static_method(
115-
registry_class,
116-
"of",
117-
RegistryKey::MINECRAFT_REGISTRYKEY_OF,
118-
&[(&kind).into(), (&id).into()],
119-
)
120-
.expect("Cannot generate RegistryKey")
121-
.l()
122-
.expect("Cannot convert to JObject")
123-
}
124-
}
100+
new_enum! {RegistryKeys [RegistryKey]: "net/minecraft/registry/RegistryKeys" {
101+
ITEM
102+
}}

rust/src/java/macros.rs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
#[macro_export]
2+
macro_rules! impl_methods {
3+
(
4+
[$class:ident];
5+
static fn $fn:ident ( $($arg:ident : $arg_ty:ty),* $(,)? ) $(-> $ret:ty)?;
6+
$($tt:tt)*
7+
) => {
8+
$crate::java::impl_methods!{[$class]; static $fn fn $fn ($($arg : $arg_ty),*) $(-> $ret)?; $($tt)*}
9+
};
10+
11+
(
12+
[$class:ident];
13+
static $raw:ident fn $fn:ident ( $($arg:ident : $arg_ty:ty),* $(,)? ) $(-> $ret:ty)?;
14+
$($tt:tt)*
15+
) => {
16+
impl $class<'_> {
17+
pub fn $fn<'local>(env: &mut ::jni::JNIEnv<'local>, $($arg : $arg_ty),*) $(-> $ret)? {
18+
let mut sig_args = Vec::new();
19+
$(
20+
let $arg = $crate::java::IntoJValue::into_jvalue($arg, env);
21+
sig_args.push(<$arg_ty as $crate::java::JSignature>::sig_type());
22+
)*
23+
24+
let sig = ["(", &sig_args.join(""), ")", $crate::java::impl_methods!(!ret $($ret)?)].join("");
25+
26+
println!("CALLING: {} : {sig}", stringify!($raw));
27+
28+
let class = env.find_class(<$class as $crate::java::JSignature>::sig()).unwrap();
29+
30+
let _ret = env
31+
.call_static_method(class, stringify!($raw), sig, &[$($arg.borrow()),*])
32+
.unwrap();
33+
34+
$crate::java::impl_methods!(#ret _ret; $($ret)?)
35+
}
36+
}
37+
38+
$crate::java::impl_methods!{[$class]; $($tt)*}
39+
};
40+
41+
(
42+
[$class:ident];
43+
pub fn $fn:ident ( $($arg:ident : $arg_ty:ty),* $(,)? ) $(-> $ret:ty)?;
44+
$($tt:tt)*
45+
) => {
46+
$crate::java::impl_methods!{[$class]; pub $fn fn $fn ($($arg : $arg_ty),*) $(-> $ret)?; $($tt)*}
47+
};
48+
49+
(
50+
[$class:ident];
51+
pub $raw:ident fn $fn:ident ( $($arg:ident : $arg_ty:ty),* $(,)? ) $(-> $ret:ty)?;
52+
$($tt:tt)*
53+
) => {
54+
impl $class<'_> {
55+
pub fn $fn<'local>(&self, env: &mut ::jni::JNIEnv<'local>, $($arg : $arg_ty),*) $(-> $ret)? {
56+
#[allow(unused_mut)]
57+
let mut sig_args: Vec<String> = Vec::new();
58+
$(
59+
let $arg = $crate::java::IntoJValue::into_jvalue($arg, env);
60+
sig_args.push(<$arg_ty as $crate::java::JSignature>::sig_type());
61+
)*
62+
63+
let sig = ["(", &sig_args.join(""), ")", $crate::java::impl_methods!(!ret $($ret)?)].join("");
64+
65+
println!("CALLING instance: {} : {sig} on {}", stringify!($raw), $class::sig());
66+
67+
let _ret = env
68+
.call_method(&self.0, stringify!($raw), sig, &[$($arg.borrow()),*])
69+
.unwrap();
70+
71+
$crate::java::impl_methods!(#ret _ret; $($ret)?)
72+
}
73+
}
74+
75+
$crate::java::impl_methods!{[$class]; $($tt)*}
76+
};
77+
78+
([$class:ident]; ) => {};
79+
80+
(!ret ()) => {"V"};
81+
(!ret) => {"V"};
82+
(!ret $ret:ty) => {&<$ret as $crate::java::JSignature>::sig_type()};
83+
84+
(#ret $i:ident; ) => {()};
85+
(#ret $i:ident; ()) => {()};
86+
(#ret $i:ident; $ret:ty) => {$i.l().unwrap().into()};
87+
}
88+
89+
#[macro_export]
90+
macro_rules! new_class {
91+
($name:ident: $jni:literal {
92+
$($tt:tt)*
93+
}) => {
94+
pub struct $name<'local>(pub ::jni::objects::JObject<'local>);
95+
96+
impl<'local> From<::jni::objects::JObject<'local>> for $name<'local> {
97+
fn from(value: ::jni::objects::JObject<'local>) -> $name<'local> {
98+
Self(value)
99+
}
100+
}
101+
102+
impl<'local> Into<::jni::objects::JObject<'local>> for $name<'local> {
103+
fn into(self) -> ::jni::objects::JObject<'local> {
104+
self.0
105+
}
106+
}
107+
108+
impl $name<'_> {
109+
#[allow(dead_code)]
110+
pub fn new<'local>(env: &mut ::jni::JNIEnv<'local>) -> $name<'local> {
111+
let class = env.find_class(<$name as $crate::java::JSignature>::sig()).unwrap();
112+
113+
env.new_object(class, "()V", &[]).unwrap().into()
114+
}
115+
}
116+
117+
impl $crate::java::JSignature for $name<'_> {
118+
fn sig() -> String {
119+
$jni.to_owned()
120+
}
121+
}
122+
123+
impl $crate::java::IntoJValue for $name<'_> {
124+
fn into_jvalue<'local>(self, env: &mut ::jni::JNIEnv<'local>) -> ::jni::objects::JValueOwned<'local> {
125+
env.new_local_ref(&self.0).unwrap().into()
126+
}
127+
}
128+
129+
impl $crate::java::IntoJValue for &$name<'_> {
130+
fn into_jvalue<'local>(self, env: &mut ::jni::JNIEnv<'local>) -> ::jni::objects::JValueOwned<'local> {
131+
env.new_local_ref(&self.0).unwrap().into()
132+
}
133+
}
134+
135+
$crate::java::impl_methods!{[$name]; $($tt)*}
136+
};
137+
}
138+
139+
#[macro_export]
140+
macro_rules! new_enum {
141+
($name:ident [$from:ident]: $jni:literal { }) => {
142+
compile_error!("Add some variant");
143+
};
144+
145+
($name:ident [$from:ident]: $jni:literal {
146+
$($k:ident),+
147+
}) => {
148+
pub enum $name {
149+
$($k,)*
150+
}
151+
152+
impl $crate::java::JSignature for $name {
153+
fn sig() -> String {
154+
$from::sig()
155+
}
156+
157+
fn sig_type() -> String {
158+
$from::sig_type()
159+
}
160+
}
161+
162+
impl $crate::java::IntoJValue for $name {
163+
fn into_jvalue<'local>(self, env: &mut ::jni::JNIEnv<'local>) -> ::jni::objects::JValueOwned<'local> {
164+
let class = env
165+
.find_class($jni)
166+
.expect(concat!("Cannot get ", stringify!($name), " class"));
167+
168+
let field = match &self {
169+
$($name::$k => stringify!($k)),*
170+
};
171+
172+
env
173+
.get_static_field(class, field, Self::sig_type())
174+
.unwrap()
175+
.l()
176+
.unwrap()
177+
.into()
178+
}
179+
}
180+
};
181+
}
182+
183+
pub use impl_methods;
184+
pub use new_class;
185+
pub use new_enum;

0 commit comments

Comments
 (0)